本節主要內容:
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()方法,控制台輸出結果如下:
- 實例化ExampleBean
- 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()方法,控制台輸出結果如下:
- 實例化ExampleBean
- 實例化ExampleBean
- 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>
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
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