Spring學習筆記之 Spring IOC容器(一)之 實例化容器,創建JavaBean對象,控制Bean實例化,setter方式注入,依賴屬性的注入,自動裝配功能實現自動屬性注入


 

 

 

 

本節主要內容:
   

   1.實例化Spring容器示例
    2.利用Spring容器創建JavaBean對象
    3.如何控制Bean實例化
    4.利用Spring實現bean屬性setter方式注入
    5.利用構造器參數實現依賴屬性的注入
    6.利用Spring的自動裝配功能實現自動屬性注入

 

本文作者:souvc

本文出處:http://www.cnblogs.com/liuhongfeng/p/4581283.html 

 

 

1 實例化Spring容器示例

 

1.1 問題

使用ApplicationContext的方式實例化Spring容器。

1.2 方案

使用ApplicationContext的方式實例化Spring容器的核心代碼如下:

    String conf = "applicationContext.xml";
    ApplicationContext ac = new ClassPathXmlApplicationContext(conf);

 

1.3 步驟

步驟一:新建工程,導入jar包

新建名為 SouvcSpringIOC  的web工程,在該工程導入5個Spring相關jar包。

 

commons-logging.jar
spring-core.jar
spring-context.jar
spring-beans.jar
spring-expression.jar


網盤下載jar包 :http://yunpan.cn/cQJhPMPRZeLH7  訪問密碼 2bf8

 

步驟二:新建Spring配置文件

與src目錄下新建Spring配置文件  applicationContext.xml  。該文件名為Spring默認的配置文件名,也可以自由定義名稱。

 

<?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
        xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:jpa="http://www.springframework.org/schema/data/jpa"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
            http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
            http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd">
</beans>

 

 

步驟三:新建類TestCase

導入JUnit4 , 用於軟件的單元測試.

新建類TestCase,在類中使用ApplicationContext的方式實例化Spring容器。

在TestCase類中添加測試方法testInitContext():

/** 測試實例化Spring容器示例 */
    @Test
    public void testInitContext() {
        String conf = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(conf);
        System.out.println(ac);
    }

 

步驟四:運行testInitContext()方法

運行testInitContext()方法,控制台輸出結果

 

org.springframework.context.support.ClassPathXmlApplicationContext@5a77a7f9: startup date [Tue Jun 16 17:22:35 CST 2015]; root of context hierarchy

 

控制台輸出以上的信息,說明實例化Spring容器成功。

 

1.4 完整代碼

TestCase類的完整代碼如下:

package com.souvc.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestCase {
    /** 測試實例化Spring容器示例 */
    @Test
    public void testInitContext() {
        String conf = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(conf);
        System.out.println(ac);
    }
}

 

applicationContext.xml完整代碼如下:

<?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
        xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:jpa="http://www.springframework.org/schema/data/jpa"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
            http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
            http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd">
</beans>

 

 

2 利用Spring容器創建JavaBean對象

 

2.1 問題

 測試Spring支持的多種JavaBean對象創建方式:

1. 用構造器來實例化的方式。

    利用Spring調用構造器 GregorianCalendar 創建 Calendar實例.

2. 使用靜態工廠方法實例化的方式。

     利用Spring調用 Calendar 的靜態工廠方法getInstance() 創建 Calendar實例.

3. 使用實例工廠方法實例化的方式。

     利用Spring創建 GregorianCalendar 對象作為工廠, 調用getTime()方法創建Date類型對象實例.

 

2.2 方案

 

1. 用構造器來實例化的方式的配置代碼如下:

<bean id="calendarObj1" class="java.util.GregorianCalendar"></bean>

bean標記中id屬性calendarObj1用於定義bean名字, 是程序代碼中獲得Spring管理bean對象的標識, 這個名字不能重復, class用於指定創建對象的類GregorianCalendar, Spring會自動的調用GregorianCalendar類的默認構造器創建bean對象實例.

 

2. 使用靜態工廠方法實例化的方式的配置代碼如下:

<bean id="calendarObj2"  class="java.util.Calendar" factory-method="getInstance"> </bean>

bean標記中id屬性calendarObj2用於定義bean名字, 是程序代碼中獲得Spring管理bean對象的標識, 這個名字不能重復, class屬性用於指定創建對象的工廠類Calendar, factory-method屬性用於指定創建對象的靜態工廠方法getInstance, Spring會自動的調用工廠類Calendar靜態工廠方法getInstance創建bean對象實例.

 

3. 使用實例工廠方法實例化的方式的配置代碼如下:

 <bean id="calendarObj3" class="java.util.GregorianCalendar"></bean>
 <bean id="dateObj" factory-bean="calendarObj3" factory-method="getTime"> </bean>

這里定義了兩個bean, 其中一個bean calendarObj3是用於創建 dateObj 對象的實例工廠.

另外一個bean標記中id屬性dateObj用於定義bean名字, 是程序代碼中獲得Spring管理bean對象的標識, 這個名字不能重復, factory-bean屬性用於指定創建對象的工廠對象calendarObj3, 前面定義的一個bean, factory-method屬性用於指定創建對象的工廠方法getTime, Spring會自動的調用工廠類Calendar靜態工廠方法getInstance創建bean對象實例.

 

2.3 步驟

步驟一:配置 applicationContext.xml, 增加Bean對象創建聲明

代碼如下所示:

    <!--  1. 用構造器來實例化的方式的配置代碼如下: -->
    <bean id="calendarObj1" class="java.util.GregorianCalendar"></bean>

    <!-- 2. 使用靜態工廠方法實例化的方式的配置代碼如下:  -->
    <bean id="calendarObj2" class="java.util.Calendar" factory-method="getInstance"></bean>

    <!-- 3. 使用實例工廠方法實例化的方式的配置代碼如下:  -->
    <bean id="calendarObj3" class="java.util.GregorianCalendar"></bean>
    <bean id="dateObj" factory-bean="calendarObj3" factory-method="getTime"> </bean>

 

步驟二:在TestCase類中增加測試方法testCreateBeanObject,測試Spring創建對象的結果

         先創建Spring容器對象, 再調用getBean方法獲得Spring創建的對象實例,並且利用輸出語句測試對象是否存在. 這個代碼中要注意: getBean方法的參數必須是上一個步驟中定義的bean標記上的id屬性的值, 否則會出現運行異常.

 

代碼如下所示:

/** 測試Spring支持的多種JavaBean對象創建方式 */
    @Test
    public void testCreateBeanObject() {
        // 實例化Spring容器示例
        String conf = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(conf);

        // 1. 用構造器來實例化的方式。
        // 利用Spring調用構造器 GregorianCalendar 創建 Calendar實例.
        // Calendar cal1 = (Calendar)ac.getBean("calendarObj1"); //方式1
        Calendar cal1 = ac.getBean("calendarObj1", Calendar.class); // 方式2
        System.out.println("cal1:" + cal1);

        // 2. 使用靜態工廠方法實例化的方式。
        // 利用Spring調用 Calendar 的靜態工廠方法getInstance() 創建 Calendar實例.
        Calendar cal2 = ac.getBean("calendarObj2", Calendar.class);
        System.out.println("cal2:" + cal2);

        // 3. 使用實例工廠方法實例化的方式。
        // 利用Spring創建 GregorianCalendar 對象作為工廠, 調用getTime()方法創建Date類型對象實例.
        Date date = ac.getBean("dateObj", Date.class);
        System.out.println("date:" + date);
    }

 

 

步驟三:運行測試方法測試bean實例化

控制台輸出結果如下所示:

cal1:java.util.GregorianCalendar[time=1434446926808,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=19,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2015,MONTH=5,WEEK_OF_YEAR=25,WEEK_OF_MONTH=3,DAY_OF_MONTH=16,DAY_OF_YEAR=167,DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=3,AM_PM=1,HOUR=5,HOUR_OF_DAY=17,MINUTE=28,SECOND=46,MILLISECOND=808,ZONE_OFFSET=28800000,DST_OFFSET=0]
cal2:java.util.GregorianCalendar[time
=1434446926837,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=19,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2015,MONTH=5,WEEK_OF_YEAR=25,WEEK_OF_MONTH=3,DAY_OF_MONTH=16,DAY_OF_YEAR=167,DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=3,AM_PM=1,HOUR=5,HOUR_OF_DAY=17,MINUTE=28,SECOND=46,MILLISECOND=837,ZONE_OFFSET=28800000,DST_OFFSET=0]
date:Tue Jun
16 17:28:46 CST 2015

 

 

2.4 完整代碼

TestCase類的testCreateBeanObject方法完整代碼如下所示:

package com.souvc.test;

import java.util.Calendar;
import java.util.Date;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestCase {
    /** 測試實例化Spring容器示例 */
    @Test
    public void testInitContext() {
        String conf = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(conf);
        System.out.println(ac);
    }

    /** 測試Spring支持的多種JavaBean對象創建方式 */
    @Test
    public void testCreateBeanObject() {
        // 實例化Spring容器示例
        String conf = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(conf);

        // 1. 用構造器來實例化的方式。
        // 利用Spring調用構造器 GregorianCalendar 創建 Calendar實例.
        // Calendar cal1 = (Calendar)ac.getBean("calendarObj1"); //方式1
        Calendar cal1 = ac.getBean("calendarObj1", Calendar.class); // 方式2
        System.out.println("cal1:" + cal1);

        // 2. 使用靜態工廠方法實例化的方式。
        // 利用Spring調用 Calendar 的靜態工廠方法getInstance() 創建 Calendar實例.
        Calendar cal2 = ac.getBean("calendarObj2", Calendar.class);
        System.out.println("cal2:" + cal2);

        // 3. 使用實例工廠方法實例化的方式。
        // 利用Spring創建 GregorianCalendar 對象作為工廠, 調用getTime()方法創建Date類型對象實例.
        Date date = ac.getBean("dateObj", Date.class);
        System.out.println("date:" + date);
    }
}

 

applicationContext.xml 源碼:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
            http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
            http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd">


    <!--  1. 用構造器來實例化的方式的配置代碼如下: -->
    <bean id="calendarObj1" class="java.util.GregorianCalendar"></bean>

    <!-- 2. 使用靜態工廠方法實例化的方式的配置代碼如下:  -->
    <bean id="calendarObj2" class="java.util.Calendar"
        factory-method="getInstance">
    </bean>

    <!-- 3. 使用實例工廠方法實例化的方式的配置代碼如下:  -->
    <bean id="calendarObj3" class="java.util.GregorianCalendar"></bean>
    <bean id="dateObj" factory-bean="calendarObj3"
        factory-method="getTime">
    </bean>



</beans>

 

 

3 如何控制Bean實例化

3.1 問題

測試Bean的作用域、Bean的生命周期回調、Bean對象的創建時機以及如何指定bean依賴關系。

3.2 步驟

步驟一:Bean對象的創建模式

1. 新建包com.souvc.dao , 新建類 ExampleBean。

package com.souvc.dao;

public class ExampleBean {

    public ExampleBean() {
        System.out.println("實例化ExampleBean");
    }

    public void execute() {
        System.out.println("執行ExampleBean處理");
    }
}

 

2. 在applicationContext.xml文件中,配置ExampleBean,代碼如下所示:

 
<bean id="exampleBean" class="com.souvc.dao.ExampleBean"></bean>

 

3. 在TestCase中新建測試方法testExampleBean(),在方法中從Spring中獲取兩個ExampleBean類型對象,通過比較操作 符“ == ” 進行比較,如果輸出結果為true,則表明兩次獲取的是同一個對象,即創建對象的方式單例模式,代碼如下所示:

 

@Test
    public void testExampleBean() {
        // 實例化Spring容器示例
        String conf = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(conf);
        // 獲取ExampleBean對象
        ExampleBean bean1 = ac.getBean("exampleBean", ExampleBean.class);
        ExampleBean bean2 = ac.getBean("exampleBean", ExampleBean.class);
        System.out.println(bean1 == bean2);
        
        
        // 關閉Spring容器, 注意AbstractApplicationContext類型定義了 close()方法
        //AbstractApplicationContext ctx = (AbstractApplicationContext) ac;
        //ctx.close();
    }

 

4. 運行testExampleBean()方法,控制台輸出結果如下:

  1. 實例化ExampleBean
  2. true

上述運行結果可以看得出在軟件運行期間ExampleBean的構造器只被調用過一次, 創建過一個對象,兩次獲得引用變量bean1, bean2,通過比較操作符“ ==” 進行比較的輸出結果為true, 說明是引用了同一個對象, 也就說明Spring容器創建Bean對象是唯一實例, 是單例對象。

 

5. 修改applicationContext.xml,設置創建Bean的模式為原型模式(prototype)

 
<!-- scope="singleton" 模式 
    <bean id="exampleBean" class="com.souvc.dao.ExampleBean" scope="singleton"></bean>-->

<!-- scope="prototype" 模式 -->
    <bean id="exampleBean" class="com.souvc.dao.ExampleBean" scope="prototype"></bean>

 

6. 再次運行testExampleBean()方法,控制台輸出結果如下:

  1. 實例化ExampleBean
  2. 實例化ExampleBean
  3. false

 

這個結果說明調用了2次ExampleBean類的構造方法創建了兩個Bean對象,比較結果是false表示bean1和bean2引用了這兩個不同的對象, 這樣創建bean就不再是單例模式了。

 

步驟二:Bean對象的初始化和銷毀

1. 修改ExampleBean類,加入方法init和方法destroy,代碼如下所示:

package com.souvc.dao;

public class ExampleBean {

    public ExampleBean() {
        System.out.println("實例化ExampleBean");
    }

    public void execute() {
        System.out.println("執行ExampleBean處理");
    }

    public void init() {
        System.out.println("初始化ExampleBean對象");
    }

    public void destroy() {
        System.out.println("銷毀ExampleBean對象");
    }
}

 

2. 修改applicationContext.xml,希望在bean對象創建后自動調用init()方法,代碼如圖-12所示:

<!-- scope="prototype" 模式 -->
    <bean id="exampleBean" class="com.souvc.dao.ExampleBean"
        scope="prototype" init-method="init">
    </bean>

 

3.運行testExampleBean()方法,自定義的初始化的方法在對象被創建后調用,如圖-13所示:

實例化ExampleBean
初始化ExampleBean對象
實例化ExampleBean
初始化ExampleBean對象
false

 

4.修改applicationContext.xml,希望在bean對象銷毀前自動調用destroy方法,bean對象在spring容器關閉的時候被銷毀,代碼如圖-14所示:

<!-- scope="prototype" 模式 -->
    <bean id="exampleBean" class="com.souvc.dao.ExampleBean"
        scope="prototype" init-method="init"  destroy-method="destroy">
    </bean>

 

5.修改testExampleBean()方法,關閉ApplicationContext對象,代碼如圖-15所示:

@Test
    public void testExampleBean() {
        // 實例化Spring容器示例
        String conf = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(conf);
        // 獲取ExampleBean對象
        ExampleBean bean1 = ac.getBean("exampleBean", ExampleBean.class);
        ExampleBean bean2 = ac.getBean("exampleBean", ExampleBean.class);
        System.out.println(bean1 == bean2);
        
        
        // 關閉Spring容器, 注意AbstractApplicationContext類型定義了 close()方法
        AbstractApplicationContext ctx = (AbstractApplicationContext) ac;
        ctx.close();
    }

 

6.運行testExampleBean()方法,控制台輸出結果如圖


 

控制台沒有輸出預期的“銷毀ExampleBean對象”的結果。原因在於applicationContext.xml文件中設置的destroy-method屬性僅僅對單例模式起作用,在prototype模式下沒有意義。

 

7.修改applicationContext.xml,使用singleton模式創建Bean對象,代碼所示:

<!-- scope="prototype" 模式 -->
    <bean id="exampleBean" class="com.souvc.dao.ExampleBean"
        scope="singleton" init-method="init"  destroy-method="destroy">
    </bean>

 

8.運行testExampleBean()方法,控制台輸出了“銷毀ExampleBean對象” ,代碼如下圖所示。


 

9.在頂級的<beans/>元素中的default-init-method屬性以及default-destroy-method屬性,可以為容器所有<bean>指定初始化回調方法以及指定銷毀回調方法,代碼如下圖所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
            http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
            http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd"
    default-init-method="init" default-destroy-method="destroy" >

 

步驟三:Bean對象的創建時機

1. 注釋testExampleBean中如圖所示的代碼。

    @Test
    public void testExampleBean() {
        // 實例化Spring容器示例
        String conf = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(conf);
        // 獲取ExampleBean對象
        //ExampleBean bean1 = ac.getBean("exampleBean", ExampleBean.class);
        //ExampleBean bean2 = ac.getBean("exampleBean", ExampleBean.class);
        //System.out.println(bean1 == bean2);
        
        
        // 關閉Spring容器, 注意AbstractApplicationContext類型定義了 close()方法
        //AbstractApplicationContext ctx = (AbstractApplicationContext) ac;
        //ctx.close();
    }

 

2. 運行testExampleBean方法,控制台輸出結果


實例化ExampleBean
初始化ExampleBean對象

 

控制台打印結果,說明默認情況下ExampleBean在Spring容器被創建時就會創建。

3. 修改applicationContext.xml,通過設置配置文件屬性lazy-init="true",可以改變Spring容器創建對象的時機,代碼如圖-22所示:

<!-- scope="prototype" 模式 -->
    <bean id="exampleBean" class="com.souvc.dao.ExampleBean"
        scope="singleton" init-method="init" destroy-method="destroy" lazy-init="true">
    </bean>

 

4.運行testExampleBean方法,控制台沒有輸出信息,因為對象並沒有被實例化,或者說,實例化被延遲了。

5. 去除 testExampleBean方法注釋掉的代碼,

@Test
    public void testExampleBean() {
        // 實例化Spring容器示例
        String conf = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(conf);
        // 獲取ExampleBean對象
        ExampleBean bean1 = ac.getBean("exampleBean", ExampleBean.class);
        ExampleBean bean2 = ac.getBean("exampleBean", ExampleBean.class);
        System.out.println(bean1 == bean2);
        
        
        // 關閉Spring容器, 注意AbstractApplicationContext類型定義了 close()方法
        AbstractApplicationContext ctx = (AbstractApplicationContext) ac;
        ctx.close();
    }

 

6.運行testExampleBean方法


 

從輸出結果可以看出,當使用ExampleBean對象時,才被創建,即,設置lazy-init="true"屬性后,對象不使用不創建。

7.在頂級的<beans/>元素中的default-lazy-init屬性,可以為容器所有<bean>指定延遲實例化特性

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
            http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
            http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd"
    default-init-method="init" default-destroy-method="destroy" default-lazy-init="true">

 

步驟四:指定bean依賴關系

1. 新建類ExampleBean1,代碼如下所示:

 
package com.souvc.dao;

public class ExampleBean1 {
    public ExampleBean1() {
        System.out.println("實例化ExampleBean1");
    }
}

 

2. 修改applicationContext.xml文件,將ExampleBean依賴ExampleBean1

<!-- scope="prototype" 模式 -->
    <bean id="exampleBean" class="com.souvc.dao.ExampleBean"
        scope="singleton" init-method="init" destroy-method="destroy"
        lazy-init="true" depends-on="exampleBean1">
    </bean>

    <!-- scope="prototype" 模式 -->
    <bean id="exampleBean1" class="com.souvc.dao.ExampleBean1"
        lazy-init="true">
    </bean>

 

3. 運行testExampleBean方法,控制台輸出結果如圖-27所示:

實例化ExampleBean1
實例化ExampleBean
初始化ExampleBean對象
true
2015-6-16 18:02:00 org.springframework.context.support.AbstractApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@2996c1b0: startup date [Tue Jun 16 18:02:00 CST 2015]; root of context hierarchy
2015-6-16 18:02:00 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
信息: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@783c342b: defining beans [calendarObj1,calendarObj2,calendarObj3,dateObj,exampleBean,exampleBean1]; root of factory hierarchy
銷毀ExampleBean對象

 

可以看出,由於ExampleBean依賴於ExampleBean1,因此在創建ExampleBean的同時,也創建了ExampleBean1。

3.3 完整代碼

ExampleBean類的完整代碼如下所示:

package com.souvc.dao;

public class ExampleBean {

    public ExampleBean() {
        System.out.println("實例化ExampleBean");
    }

    public void execute() {
        System.out.println("執行ExampleBean處理");
    }

    public void init() {
        System.out.println("初始化ExampleBean對象");
    }

    public void destroy() {
        System.out.println("銷毀ExampleBean對象");
    }
}

 

ExampleBean1 源碼:

package com.souvc.dao;

public class ExampleBean1 {
    public ExampleBean1() {
        System.out.println("實例化ExampleBean1");
    }
}

 

TestCase 源碼:

package com.souvc.test;

import java.util.Calendar;
import java.util.Date;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.souvc.dao.ExampleBean;

public class TestCase {
    /** 測試實例化Spring容器示例 */
    @Test
    public void testInitContext() {
        String conf = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(conf);
        System.out.println(ac);
    }

    /** 測試Spring支持的多種JavaBean對象創建方式 */
    @Test
    public void testCreateBeanObject() {
        // 實例化Spring容器示例
        String conf = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(conf);

        // 1. 用構造器來實例化的方式。
        // 利用Spring調用構造器 GregorianCalendar 創建 Calendar實例.
        // Calendar cal1 = (Calendar)ac.getBean("calendarObj1"); //方式1
        Calendar cal1 = ac.getBean("calendarObj1", Calendar.class); // 方式2
        System.out.println("cal1:" + cal1);

        // 2. 使用靜態工廠方法實例化的方式。
        // 利用Spring調用 Calendar 的靜態工廠方法getInstance() 創建 Calendar實例.
        Calendar cal2 = ac.getBean("calendarObj2", Calendar.class);
        System.out.println("cal2:" + cal2);

        // 3. 使用實例工廠方法實例化的方式。
        // 利用Spring創建 GregorianCalendar 對象作為工廠, 調用getTime()方法創建Date類型對象實例.
        Date date = ac.getBean("dateObj", Date.class);
        System.out.println("date:" + date);
    }

    @Test
    public void testExampleBean() {
        // 實例化Spring容器示例
        String conf = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(conf);
        // 獲取ExampleBean對象
        ExampleBean bean1 = ac.getBean("exampleBean", ExampleBean.class);
        ExampleBean bean2 = ac.getBean("exampleBean", ExampleBean.class);
        System.out.println(bean1 == bean2);
        
        
        // 關閉Spring容器, 注意AbstractApplicationContext類型定義了 close()方法
        AbstractApplicationContext ctx = (AbstractApplicationContext) ac;
        ctx.close();
    }

}

 

applicationContext.xml 源碼:

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
            http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
            http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd"
    default-init-method="init" default-destroy-method="destroy"
    default-lazy-init="true">


    <!--  1. 用構造器來實例化的方式的配置代碼如下: -->
    <bean id="calendarObj1" class="java.util.GregorianCalendar"></bean>

    <!-- 2. 使用靜態工廠方法實例化的方式的配置代碼如下:  -->
    <bean id="calendarObj2" class="java.util.Calendar"
        factory-method="getInstance">
    </bean>

    <!-- 3. 使用實例工廠方法實例化的方式的配置代碼如下:  -->
    <bean id="calendarObj3" class="java.util.GregorianCalendar"></bean>
    <bean id="dateObj" factory-bean="calendarObj3"
        factory-method="getTime">
    </bean>

    <!-- scope="singleton" 模式 
        <bean id="exampleBean" class="com.souvc.dao.ExampleBean" scope="singleton"></bean>-->

    <!-- scope="prototype" 模式 -->
    <bean id="exampleBean" class="com.souvc.dao.ExampleBean"
        scope="singleton" init-method="init" destroy-method="destroy"
        lazy-init="true" depends-on="exampleBean1">
    </bean>

    <!-- scope="prototype" 模式 -->
    <bean id="exampleBean1" class="com.souvc.dao.ExampleBean1"
        lazy-init="true">
    </bean>

</beans>

 

 

4 利用Spring實現bean屬性setter方式注入

 

4.1 問題

JDBCDataSource類封裝了管理數據庫連接的方法getConnection(), 這個方法在執行之前需要數據庫連接參數: 數據庫驅動, 連接URL, 用戶名和密碼.

JDBCDataSource代碼如下:

package com.souvc.dao;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class JDBCDataSource implements Serializable {

    private String driver;
    private String url;
    private String user;
    private String pwd;

    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        try {
            // 注冊數據庫驅動
            Class.forName(driver);
            this.driver = driver;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public Connection getConnection() throws SQLException {
        Connection conn = DriverManager.getConnection(url, user, pwd);
        return conn;
    }

    public void close(Connection conn) {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

 

 

利用Spring實現JDBCDataSource對象的創建, 再使用setter注入的方式將數據庫連接參數注入給JDBCDataSource。這樣就可以正常的調用getConnection()方法獲得數據庫連接了.

4.2 方案

利用Spring配置文件applicationContext.xml配置bean, 並且setter參數注入JDBCDataSource的連接參數, 這樣Spring在創建JDBCDataSource對象以后就會自動化的調用setter方法注入數據庫連接參數.

applicationContext.xml配置bean參考代碼如下:

 
<!-- setter注入  oracle 
        <bean id="dataSource" class="com.souvc.dao.JDBCDataSource">
        <property name="driver" value="oracle.jdbc.OracleDriver"></property>
        <property name="url"
        value="jdbc:oracle:thin:@localhost:1521:ora1">
        </property>
        <property name="user" value="root"></property>
        <property name="pwd" value="123456"></property>
        </bean>
    -->

    <!-- setter注入 mysql -->
    <bean id="dataSource" class="com.souvc.dao.JDBCDataSource">
        <property name="driver" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/csdn">
        </property>
        <property name="user" value="root"></property>
        <property name="pwd" value="123456"></property>
    </bean>

 

 
以上的源碼如下: http://yunpan.cn/cQVM3ZYbpZzrV  訪問密碼 42ea
 
 
 

4.3 步驟

步驟一:新建工程,導入jar包

新建名為SouvcSpringIoC的web工程,在該工程導入如下面所示的6個jar包, 包括Spring API 和 Oracle JDBC Driver或者mysql JDBC DRIVER。

 

commons-logging.jar
spring-core.jar
spring-context.jar
spring-beans.jar
spring-expression.jar
mysql-connector-java-5.1.7-bin.jar

ojdbc5.jar

 

步驟二:創建被Spring管理的JDBCDataScorce類, 用於連接到數據庫

代碼如下所示:

package com.souvc.dao;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class JDBCDataSource implements Serializable {

    private String driver;
    private String url;
    private String user;
    private String pwd;

    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        try {
            // 注冊數據庫驅動
            Class.forName(driver);
            this.driver = driver;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public Connection getConnection() throws SQLException {
        Connection conn = DriverManager.getConnection(url, user, pwd);
        return conn;
    }

    public void close(Connection conn) {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

 

 

步驟三:新建applicationContext.xml, 並且增加setter代碼注入JDBC參數

在配置文件中聲明JDBCDataSource實例的bean ID為"dataSource", 該文件的核心代碼如圖-29所示:

<!-- setter注入 mysql -->
    <bean id="dataSource" class="com.souvc.dao.JDBCDataSource">
        <property name="driver" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/test">
        </property>
        <property name="user" value="root"></property>
        <property name="pwd" value="123456"></property>
    </bean>

 

步驟四:新建TestCase類,添加測試方法testJDBCDataSource()

新建的testJDBCDataSource()方法中,從Spring中獲取ID為"dataSource"的 JDBCDataSource對象, Spring會在創建JDBCDataSource對象之后調用setter方法注入JDBC連接參數:

package com.souvc.test;

import java.sql.Connection;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.souvc.dao.JDBCDataSource;

public class TestCase {
    /** Setter 注入測試 */
    @Test
    public void testJDBCDataSource() throws Exception {
        String conf = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(conf);
        System.out.println(ac);
        JDBCDataSource ds = ac.getBean("dataSource", JDBCDataSource.class);
        Connection conn = ds.getConnection();
        System.out.println(conn);
    }
}

 

步驟五:運行testJDBCDataSource方法

運行testJDBCDataSource方法,控制台的輸出結果:

org.springframework.context.support.ClassPathXmlApplicationContext@1a9334: startup date [Wed Jun 17 09:19:41 CST 2015]; root of context hierarchy
com.mysql.jdbc.ConnectionImpl@9a8a68

如果能夠輸出如上結果, 說明能夠成功的獲取Oracle JDBC 連接, 也就說明Spring成功的調用Setter方法注入了數據庫連接參數。

4.4 完整代碼

JDBCDataSource類的完整代碼如下所示:

package com.souvc.dao;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class JDBCDataSource implements Serializable {

    private String driver;
    private String url;
    private String user;
    private String pwd;

    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        try {
            // 注冊數據庫驅動
            Class.forName(driver);
            this.driver = driver;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public Connection getConnection() throws SQLException {
        Connection conn = DriverManager.getConnection(url, user, pwd);
        return conn;
    }

    public void close(Connection conn) {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

 

 
 

TestCase類的完整代碼如下所示:

package com.souvc.test;

import java.sql.Connection;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.souvc.dao.JDBCDataSource;

public class TestCase {
    /** Setter 注入測試 */
    @Test
    public void testJDBCDataSource() throws Exception {
        String conf = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(conf);
        System.out.println(ac);
        JDBCDataSource ds = ac.getBean("dataSource", JDBCDataSource.class);
        Connection conn = ds.getConnection();
        System.out.println(conn);
    }
}

 

applicationContext.xml文件的完整代碼如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
            http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
            http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd">

    <!-- setter注入  oracle 
        <bean id="dataSource" class="com.souvc.dao.JDBCDataSource">
        <property name="driver" value="oracle.jdbc.OracleDriver"></property>
        <property name="url"
        value="jdbc:oracle:thin:@localhost:1521:ora1">
        </property>
        <property name="user" value="root"></property>
        <property name="pwd" value="123456"></property>
        </bean>
    -->

    <!-- setter注入 mysql -->
    <bean id="dataSource" class="com.souvc.dao.JDBCDataSource">
        <property name="driver" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/cnblogs">
        </property>
        <property name="user" value="root"></property>
        <property name="pwd" value="123456"></property>
    </bean>


</beans>

 

 

5 利用構造器參數實現依賴屬性的注入

5.1 問題

OracleUserDAO是經典的數據訪問接口實現類, 這個類工作必須依賴Oracle數據庫連接來工作, JDBCDataSource實例可以提供Oracle數據庫的連接, OracleUserDAO類 采用構造器參數的方式, 依賴JDBCDataSource類, 這樣的好處是創建OracleUserDAO類必須有參數JDBCDataSource對象實例. Spring支持利用構造器注入參數創建Bean對象的方式.

UserDAO接口參考如下:

 

package com.souvc.dao;

/**
 * 用戶數據訪問對象接口
 */
public interface UserDAO {
    /** 根據唯一用戶名查詢系統用戶, 如果沒有找到用戶信息返回null */
    public User findByName(String name);
}

 

 

User類型參考如下:

package com.souvc.entity;

import java.io.Serializable;
    public class User implements Serializable  {
        private int id;
        private String name;
        private String pwd;
        private String phone;
        
        public User() {
        }
        public User(int id, String name, String pwd, String phone) {
            this.id = id;
            this.name = name;
            this.pwd = pwd;
            this.phone = phone;
        }
        public User(String name, String pwd, String phone) {
            super();
            this.name = name;
            this.pwd = pwd;
            this.phone = phone;
        }
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getPwd() {
            return pwd;
        }
        public void setPwd(String pwd) {
            this.pwd = pwd;
        }
        public String getPhone() {
            return phone;
        }
        public void setPhone(String phone) {
            this.phone = phone;
        }
        @Override
        public int hashCode() {
            return id;
        }
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (obj instanceof User) {
                User o = (User) obj;
                return this.id == o.id;
            }
            return true;
        }
        
        @Override
        public String toString() {
            return id+","+name+","+pwd+","+phone;
        }
    }

 

 

OracleUserDAO類參考如下:

package com.souvc.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class OracleUserDAO implements UserDAO {

    private JDBCDataSource dataSource;

    /** 創建 OracleUserDAO 對象必須依賴於JDBCDataSource實例 */
    public OracleUserDAO(JDBCDataSource dataSource) {
        this.dataSource = dataSource;
    }

    /** 根據唯一用戶名查詢系統用戶, 如果沒有找到用戶信息返回null */
    public User findByName(String name) {
        System.out.println("利用JDBC技術查找User信息");
        String sql = "select id, name, pwd, phone  from USERS where name=?";
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setString(1, name);
            ResultSet rs = ps.executeQuery();
            User user = null;
            while (rs.next()) {
                user = new User();
                user.setId(rs.getInt("id"));
                user.setName(rs.getString("name"));
                user.setPwd(rs.getString("pwd"));
                user.setPhone(rs.getString("phone"));
            }
            rs.close();
            ps.close();
            return user;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            dataSource.close(conn);
        }
    }
}

 

sql語句:

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `tb_users`
-- ----------------------------
DROP TABLE IF EXISTS `tb_users`;
CREATE TABLE `tb_users` (
  `id` int(10) NOT NULL,
  `name` varchar(25) default NULL,
  `pwd` varchar(25) default NULL,
  `phone` varchar(11) default NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_users
-- ----------------------------
INSERT INTO `tb_users` VALUES ('1', 'tom', '123456', '18976546545');

 

 

5.2 方案

Spring支持利用構造器注入參數實例化Bean方式。只要在Spring的配置文件中增加構造器參數constructor-arg, Spring就會自動的調用有參數的構造器創建bean對象實例, 整個過程無需程序編碼只需要配置applicationContext.xml文件即可, 代碼參考如下:

<!-- setter注入 mysql -->
    <bean id="dataSource" class="com.souvc.dao.JDBCDataSource">
        <property name="driver" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/test">
        </property>
        <property name="user" value="root"></property>
        <property name="pwd" value="123456"></property>
    </bean>

    <!-- 構造器注入 -->
    <bean id="userDAO" class="com.souvc.dao.MysqlUserDAO">
        <!-- 利用構造器參數注入bean的屬性 -->
        <constructor-arg name="dataSource" ref="dataSource" />
    </bean>

 

5.3 步驟

步驟一:新建業務實體類: User類

User類代表軟件中的用戶實例類型, 用戶對象信息存儲在Oracle數據庫中.User類代碼如下所示:

package com.souvc.entity;

import java.io.Serializable;
    public class User implements Serializable  {
        private int id;
        private String name;
        private String pwd;
        private String phone;
        
        public User() {
        }
        public User(int id, String name, String pwd, String phone) {
            this.id = id;
            this.name = name;
            this.pwd = pwd;
            this.phone = phone;
        }
        public User(String name, String pwd, String phone) {
            super();
            this.name = name;
            this.pwd = pwd;
            this.phone = phone;
        }
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getPwd() {
            return pwd;
        }
        public void setPwd(String pwd) {
            this.pwd = pwd;
        }
        public String getPhone() {
            return phone;
        }
        public void setPhone(String phone) {
            this.phone = phone;
        }
        @Override
        public int hashCode() {
            return id;
        }
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (obj instanceof User) {
                User o = (User) obj;
                return this.id == o.id;
            }
            return true;
        }
        
        @Override
        public String toString() {
            return id+","+name+","+pwd+","+phone;
        }
    }

 

步驟二:創建Oracle數據庫初始化SQL腳本, 並且執行

創建Oracle數據庫的初始化SQL腳本, 在數據庫中創建Users表, 並且存入實例數據用於測試需要, 在Oracle上執行這個SQL腳本. Oracle初始化SQL腳本參考如下:

 

    -- 創建用戶表
    CREATE TABLE tb_users
    (
      ID NUMBER(7, 0) , 
      NAME VARCHAR2(50) , 
      PWD VARCHAR2(50), 
      PHONE VARCHAR2(50) ,
      PRIMARY KEY (id),
      -- 登錄用戶名唯一約束
      constraint name_unique unique(name)
    );
    -- 用戶ID生成序列
    CREATE SEQUENCE SEQ_USERS;
    -- 向數據庫插入模擬數據
    insert into tb_users(id, name, pwd, phone) values (SEQ_USERS.nextval, 'Tom', '123', '110');
    insert into tb_users(id, name, pwd, phone) values (SEQ_USERS.nextval, 'Jerry', 'abc', '119');
    insert into tb_users(id, name, pwd, phone) values (SEQ_USERS.nextval, 'Andy', '456', '112');

 

Mysql 腳本:

 

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `tb_users`
-- ----------------------------
DROP TABLE IF EXISTS `tb_users`;
CREATE TABLE `tb_users` (
  `id` int(10) NOT NULL,
  `name` varchar(25) default NULL,
  `pwd` varchar(25) default NULL,
  `phone` varchar(11) default NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_users
-- ----------------------------
INSERT INTO `tb_users` VALUES ('1', 'tom', '123456', '18976546545');

 

步驟三:創建UserDAO接口, 定義用戶查詢功能

創建UserDAO接口, 聲明用戶數據查詢方法findByName, 該方法從數據庫中根據唯一的用戶名查詢用戶對象, 如果沒有查詢到對象返回null. 參考代碼如下:

package com.souvc.dao;

import com.souvc.entity.User;

/**
 * 用戶數據訪問對象接口
 */
public interface UserDAO {
    /** 根據唯一用戶名查詢系統用戶, 如果沒有找到用戶信息返回null */
    public User findByName(String name);
}

 

 
 

步驟四:創建OracleUserDAO類,實現UserDAO接口定義的功能

創建OracleUserDAO類, 實現UserDAO接口的findByName方法, 該方法用戶從數據庫中根據唯一的用戶名查詢用戶對象, 如果沒有查詢到對象返回null. 這個方法的實現必須依賴於JDBCDataSource屬性, 需要利用JDBCDataSource獲得數據庫連接, 進行數據查詢得到用戶數據. 參考代碼如下:

package com.souvc.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.souvc.entity.User;

public class OracleUserDAO implements UserDAO {

    private JDBCDataSource dataSource;

    /** 創建 OracleUserDAO 對象必須依賴於JDBCDataSource實例 */
    public OracleUserDAO(JDBCDataSource dataSource) {
        this.dataSource = dataSource;
    }

    /** 根據唯一用戶名查詢系統用戶, 如果沒有找到用戶信息返回null */
    public User findByName(String name) {
        System.out.println("利用JDBC技術查找User信息");
        String sql = "select id, name, pwd, phone  from USERS where name=?";
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setString(1, name);
            ResultSet rs = ps.executeQuery();
            User user = null;
            while (rs.next()) {
                user = new User();
                user.setId(rs.getInt("id"));
                user.setName(rs.getString("name"));
                user.setPwd(rs.getString("pwd"));
                user.setPhone(rs.getString("phone"));
            }
            rs.close();
            ps.close();
            return user;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            dataSource.close(conn);
        }
    }
}

 

 
package com.souvc.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.souvc.entity.User;

public class MysqlUserDAO {

    private JDBCDataSource dataSource;

    /** 創建 MysqlUserDAO 對象必須依賴於JDBCDataSource實例 */
    public MysqlUserDAO(JDBCDataSource dataSource) {
        this.dataSource = dataSource;
    }

    /** 根據唯一用戶名查詢系統用戶, 如果沒有找到用戶信息返回null */
    public User findByName(String name) {
        System.out.println("利用JDBC技術查找User信息");
        String sql = "select id, name, pwd, phone  from USERS where name=?";
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setString(1, name);
            ResultSet rs = ps.executeQuery();
            User user = null;
            while (rs.next()) {
                user = new User();
                user.setId(rs.getInt("id"));
                user.setName(rs.getString("name"));
                user.setPwd(rs.getString("pwd"));
                user.setPhone(rs.getString("phone"));
            }
            rs.close();
            ps.close();
            return user;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            dataSource.close(conn);
        }
    }
}

 

步驟五:配置Spring添加OracleUserDAO的bean定義

在applicationContext.xml文件中增加OracleUserDAO的Bean定義, 利用構造器初始化屬性dataSource, Spring會自動調用OracleUserDAO有參數構造器創建OracleUserDAO實例, 其中userDAO是 bean ID.

<!-- 構造器注入 -->
    <bean id="userDAO" class="com.souvc.dao.MysqlUserDAO">
        <!-- 利用構造器參數注入bean的屬性 -->
        <constructor-arg name="dataSource" ref="dataSource" />
    </bean>

 

dataSource為按構造參數注入, 這個參數是引用了id為dataSource的Bean對象.

步驟六:創建測試方法testOracleUserDAO()測試構造器注入

新建testOracleUserDAO方法,在方法中利用userDAO作為Bean ID獲取OracleUserDAO對象, Spring會自動的調用OracleUserDAO的有參數構造器, 注入dataSource對象, 創建OracleUserDAO對象. 再調用findByName方法測試是否能夠正確連接Oracle並查詢得到用戶信息.


 

 

步驟七:運行testOracleUserDAO方法

運行testOracleUserDAO方法,控制台的輸出結果


從輸出結果可以看出調用到了OracleUserDAO對象的findByName方法, 說明Spring正確的使用構造器注入的方式bean對象將dataSource注入OracleUserDAO對象內部, 並且有正確的執行結果。

5.4 完整代碼

User類的完整代碼如下所示:

package com.souvc.entity;

import java.io.Serializable;
    public class User implements Serializable  {
        private int id;
        private String name;
        private String pwd;
        private String phone;
        
        public User() {
        }
        public User(int id, String name, String pwd, String phone) {
            this.id = id;
            this.name = name;
            this.pwd = pwd;
            this.phone = phone;
        }
        public User(String name, String pwd, String phone) {
            super();
            this.name = name;
            this.pwd = pwd;
            this.phone = phone;
        }
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getPwd() {
            return pwd;
        }
        public void setPwd(String pwd) {
            this.pwd = pwd;
        }
        public String getPhone() {
            return phone;
        }
        public void setPhone(String phone) {
            this.phone = phone;
        }
        @Override
        public int hashCode() {
            return id;
        }
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (obj instanceof User) {
                User o = (User) obj;
                return this.id == o.id;
            }
            return true;
        }
        
        @Override
        public String toString() {
            return id+","+name+","+pwd+","+phone;
        }
    }

 

 

oracle.sql文件的完整代碼如下所示:

 
 
    -- 創建用戶表
    CREATE TABLE tb_users
    (
      ID NUMBER(7, 0) , 
      NAME VARCHAR2(50) , 
      PWD VARCHAR2(50), 
      PHONE VARCHAR2(50) ,
      PRIMARY KEY (id),
      -- 登錄用戶名唯一約束
      constraint name_unique unique(name)
    );
    -- 用戶ID生成序列
    CREATE SEQUENCE SEQ_USERS;
    -- 向數據庫插入模擬數據
    insert into tb_users(id, name, pwd, phone) values (SEQ_USERS.nextval, 'Tom', '123', '110');
    insert into tb_users(id, name, pwd, phone) values (SEQ_USERS.nextval, 'Jerry', 'abc', '119');
    insert into tb_users(id, name, pwd, phone) values (SEQ_USERS.nextval, 'Andy', '456', '112');

 

 
 
SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `tb_users`
-- ----------------------------
DROP TABLE IF EXISTS `tb_users`;
CREATE TABLE `tb_users` (
  `id` int(10) NOT NULL,
  `name` varchar(25) default NULL,
  `pwd` varchar(25) default NULL,
  `phone` varchar(11) default NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_users
-- ----------------------------
INSERT INTO `tb_users` VALUES ('1', 'tom', '123456', '18976546545');

 

UserDAO文件的完整代碼如下所示:

package com.souvc.dao;

import com.souvc.entity.User;

/**
 * 用戶數據訪問對象接口
 */
public interface UserDAO {
    /** 根據唯一用戶名查詢系統用戶, 如果沒有找到用戶信息返回null */
    public User findByName(String name);
}

 

OracleUserDAO文件的完整代碼如下所示:

 
package com.souvc.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.souvc.entity.User;

public class OracleUserDAO implements UserDAO {

    private JDBCDataSource dataSource;

    /** 創建 OracleUserDAO 對象必須依賴於JDBCDataSource實例 */
    public OracleUserDAO(JDBCDataSource dataSource) {
        this.dataSource = dataSource;
    }

    /** 根據唯一用戶名查詢系統用戶, 如果沒有找到用戶信息返回null */
    public User findByName(String name) {
        System.out.println("利用JDBC技術查找User信息");
        String sql = "select id, name, pwd, phone  from tb_users where name=?";
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setString(1, name);
            ResultSet rs = ps.executeQuery();
            User user = null;
            while (rs.next()) {
                user = new User();
                user.setId(rs.getInt("id"));
                user.setName(rs.getString("name"));
                user.setPwd(rs.getString("pwd"));
                user.setPhone(rs.getString("phone"));
            }
            rs.close();
            ps.close();
            return user;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            dataSource.close(conn);
        }
    }
}

 

 
 
 
package com.souvc.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.souvc.entity.User;

public class MysqlUserDAO {

    private JDBCDataSource dataSource;

    /** 創建 MysqlUserDAO 對象必須依賴於JDBCDataSource實例 */
    public MysqlUserDAO(JDBCDataSource dataSource) {
        this.dataSource = dataSource;
    }

    /** 根據唯一用戶名查詢系統用戶, 如果沒有找到用戶信息返回null */
    public User findByName(String name) {
        System.out.println("利用JDBC技術查找User信息");
        String sql = "select id, name, pwd, phone  from tb_users where name=?";
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setString(1, name);
            ResultSet rs = ps.executeQuery();
            User user = null;
            while (rs.next()) {
                user = new User();
                user.setId(rs.getInt("id"));
                user.setName(rs.getString("name"));
                user.setPwd(rs.getString("pwd"));
                user.setPhone(rs.getString("phone"));
            }
            rs.close();
            ps.close();
            return user;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            dataSource.close(conn);
        }
    }
}

 

 
 

applicationContext.xml文件的完整代碼如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
            http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
            http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd">

    <!-- setter注入  oracle 
        <bean id="dataSource" class="com.souvc.dao.JDBCDataSource">
        <property name="driver" value="oracle.jdbc.OracleDriver"></property>
        <property name="url"
        value="jdbc:oracle:thin:@localhost:1521:ora1">
        </property>
        <property name="user" value="root"></property>
        <property name="pwd" value="123456"></property>
        </bean>
    -->

    <!-- setter注入 mysql -->
    <bean id="dataSource" class="com.souvc.dao.JDBCDataSource">
        <property name="driver" value="com.mysql.jdbc.Driver"></property>
        <property name="url"
            value="jdbc:mysql://localhost:3306/cnblogs">
        </property>
        <property name="user" value="root"></property>
        <property name="pwd" value="123456"></property>
    </bean>

    <!-- 構造器注入 -->
    <bean id="userDAO" class="com.souvc.dao.MysqlUserDAO">
        <!-- 利用構造器參數注入bean的屬性 -->
        <constructor-arg name="dataSource" ref="dataSource" />
    </bean>


</beans>

 

 

TestCase文件的完整代碼如下所示:

 

package com.souvc.test;

import java.sql.Connection;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.souvc.dao.JDBCDataSource;
import com.souvc.dao.UserDAO;
import com.souvc.entity.User;

public class TestCase {
    /** Setter 注入測試 */
    @Test
    public void testJDBCDataSource() throws Exception {
        String conf = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(conf);
        System.out.println(ac);
        JDBCDataSource ds = ac.getBean("dataSource", JDBCDataSource.class);
        Connection conn = ds.getConnection();
        System.out.println(conn);
    }

    /** 構造器參數注入 */
    @Test
    public void testMysqlUserDAO() {
        String conf = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(conf);
        // 獲取MysqlUserDAO的實例
        UserDAO userDAO = ac.getBean("userDAO", UserDAO.class);
        // 查詢用戶對象
        User tom = userDAO.findByName("tom");
        System.out.println(tom);
    }

}

 

 

 

本文作者:souvc

本文出處:http://www.cnblogs.com/liuhongfeng/p/4581283.html 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM