一、依賴注入方式
對於spring配置一個bean時,如果需要給該bean提供一些初始化參數,則需要通過依賴注入方式,所謂的依賴注入就是通過spring將bean所需要的一些參數傳遞到bean實例對象的過程,spring的依賴注入有3種方式:
·使用屬性的setter方法注入 ,這是最常用的方式;
·使用構造器注入;
·使用Filed注入(用於注解方式)。
1.使用屬性注入
屬性注入即通過setXxx()方法注入Bean的屬性值或依賴對象,由於屬性注入方式具有可選擇性和靈活性高的優點,因此屬性注入是實際應用中最常采用的注入方式。
<bean id=”……” class=”……”> <property name=”屬性1” value=”……”/> <property name=”屬性2” value=”……”/> …… </bean>
屬性注入要求Bean提供一個默認的構造函數,並為需要注入的屬性提供對應的Setter方法。Spring先調用Bean的默認構造函數實例化Bean對象,然后通過反射的方式調用Setter方法注入屬性值。來看一個簡單的例子。
package com.spring.model; public class Car { private int maxSpeed; private String brand; private double price; public int getMaxSpeed() { return maxSpeed; } //一定要寫被注入對象的set方法 public void setMaxSpeed(int maxSpeed) { this.maxSpeed = maxSpeed; } public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public void run(){ System.out.println("brand:"+brand+",maxSpeed:"+maxSpeed+",price:"+price); } }
Car類中定義了3個屬性,並分別提供了對應的Setter方法。(注:默認構造函數是不帶參的構造函數。Java語言規定如果類中沒有定義任何構造函數,則JVM自動為其生成一個默認的構造函數。反之,如果類中顯示定義了構造函數,則JVM不會為其生成默認的構造函數。所以假設Car類中顯示定義了一個帶參的構造函數,如public Car(String brand),則需要同時提供一個默認構造函數public Car(),否則使用屬性注入時將拋出異常。)
下面在Spring配置文件中對Car進行屬性注入:
<!-- 屬性注入 --> <bean id="car" class="com.spring.model.Car"> <property name="maxSpeed" value="200"></property> <property name="brand" value="紅旗CA72"></property> <property name="price" value="200000.00"></property> </bean>
在上述代碼中配置了一個Bean,並為該Bean的3個屬性提供了屬性值。具體來說,Bean的每一個屬性對應一個<property>標簽,name為屬性的名稱,在Bean實現類中擁有與其對應的Setter方法:maxSpeed對應setMaxSpeed(),brand對應setBrand()。
需要指出的是:Spring只會檢查Bean中是否有對應的Setter方法,至於Bean中是否有對應的屬性變量則不做要求。例如配置文件中<property name="brand"/>的屬性配置項僅要求Car類中擁有setBrand()方法,但Car類不一定要擁有brand成員變量。
測試方法:
/** * 屬性注入 */ @Test public void test(){ //讀取配置文件 ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); //獲取bean的實例 Car car=(Car) ctx.getBean("car"); car.run(); }
2.構造函數注入
構造函數注入是除屬性注入之外的另一種常用的注入方式,它保證一些必要的屬性在Bean實例化時就得到設置,並且確保了Bean實例在實例化后就可以使用。
使用方式:
第一,在類中,不用為屬性設置setter方法,但是需要生成該類帶參的構造方法。
第二,在配置文件中配置該類的bean,並配置構造器,在配置構造器中用到了<constructor-arg>節點,該節點有四個屬性:
· index是索引,指定注入的屬性,從0開始;
· type是指該屬性所對應的類型;
· ref 是指引用的依賴對象;
· value 當注入的不是依賴對象,而是基本數據類型時,就用value;
(1)按類型匹配入參
如果任何可用的Car對象都必須提供maxSpeed、brand和price的值,使用屬性注入方式只能人為在配置時提供保證,而無法在語法級提供保證,這時通過構造函數注入就可以很好地滿足這一要求。使用構造函數注入的前提是Bean必須提供帶參的構造函數,下面為Car提供一個可設置maxSpeed、brand和price屬性的構造函數。
package com.spring.model; public class Car { private int maxSpeed; private String brand; private double price; //帶參構造方法 public Car(int maxSpeed,String brand, double price){ this.maxSpeed=maxSpeed; this.brand=brand; this.price=price; } public void run(){ System.out.println("brand:"+brand+",maxSpeed:"+maxSpeed+",price:"+price); } }
構造函數注入的配置方式和屬性注入方式的配置有所不同,在spring配置文件中使用構造函數注入裝配這個Car Bean。
<!-- 構造函數注入(按類型匹配) --> <bean id="car1" class="com.spring.model.Car"> <constructor-arg type="int" value="300"></constructor-arg> <constructor-arg type="java.lang.String" value="寶馬"></constructor-arg> <constructor-arg type="double" value="300000.00"></constructor-arg> </bean>
在<constructor-arg>的元素中有一個type屬性,它表示構造函數中參數的類型,為spring提供了判斷配置項和構造函數入參對應關系的“信息”。
(2)按索引匹配入參
我們知道,Java語言通過入參的類型及順序區分不同的重載方法,對於上面代碼中的Car類,Spring僅通過type屬性指定的參數類型就可以知道“寶馬”對應String類型的brand入參,而“300000.00”對應double類型的price入參。但是,如果Car構造函數3個入參的類型相同,僅通過type就無法確定對應關系了,這時需要通過入參索引的方式進行確定。
為了更好地演示按索引匹配入參的配置方式,特意對Car構造函數進行一下調整。
public Car(String brand, String corp,double price){ this.brand=brand; this.corp=corp; this.price=price; }
brand和corp的入參類型都是String,所以String將無法確定type為String的<constructor-arg>到底對應的是brand還是corp。但是,通過顯示指定參數的索引能夠消除這種不確定性,如下所示。
<!-- 構造函數注入(按索引匹配) --> <bean id="car2" class="com.spring.model.Car"> <!-- 注意索引從0開始 --> <constructor-arg index="0" value="寶馬"></constructor-arg> <constructor-arg index="1" value="中國一汽"></constructor-arg> <constructor-arg index="2" value="300000.00"></constructor-arg> </bean>
構造函數第一個參數索引為0,第二個為1,以此類推,因此很容易知道“寶馬”對應brand入參,而“中國一汽”對應corp入參。
(3)聯合使用類型和索引匹配入參
有時需要聯合使用type和index才能確定匹配項和構造函數入參的對應關系,看下面的代碼。
public Car(String brand, String corp,double price){ this.brand=brand; this.corp=corp; this.price=price; } public Car(String brand, String corp,int maxSpeed){ this.brand=brand; this.corp=corp; this.maxSpeed=maxSpeed; }
這里,Car擁有兩個重載的構造函數,它們都有三個入參。針對這種情況,按照入參索引的配置方式又難以滿足要求了,這時需要聯合使用<constructor-arg>的type和index才能解決問題,看下面代碼。
<!-- 構造函數注入(通過入參類型和位置索引確定對應關系) --> <!-- 對應public Car(String brand, String corp,int maxSpeed)構造函數 --> <bean id="car3" class="com.spring.model.Car"> <constructor-arg index="0" type="java.lang.String" value="奔馳"></constructor-arg> <constructor-arg index="1" type="java.lang.String" value="中國一汽"></constructor-arg> <constructor-arg index="2" type="int" value="200"></constructor-arg> </bean>
對於上面的兩個構造函數,如果僅通過index進行配置,Spring將無法確定第3個入參配置項究竟是對應int的maxSpeed還是double的price,采用索引匹配時,真正引起歧義的地方在於第3個入參,因此僅需要明確指定第3個入參的類型就可以取消歧義了。所以在上面的代碼中,第1個和第2個<constructor-arg>元素的type屬性可以去除。
對於由於參數數目相同而類型不同所引起的潛在配置歧義問題,Spring容器可以正確啟動且不會給出報錯信息,它將隨機采用一個匹配的構造函數實例化Bean,而被選擇的構造函數可能並不是用戶所希望的。因此,必須特別謹慎,以避免潛在的錯誤。
3.使用字段(Filed)注入(用於注解方式)
除了上面講到的使用屬性的setter方法或使用構造器方法來注入依賴對象,還有一種注入依賴對象的方法,就是使用注解。
來看一個例子,首先不使用注解的方式。
新建一個業務接口:
package com.spring.service; public interface ICommonService { public void add(); }
實現類:
package com.spring.service.impl; import com.spring.dao.ICommonDao; import com.spring.service.ICommonService; public class CommonServiceImpl implements ICommonService{ private ICommonDao commonDao; // 依賴注入DAO組件所需的setter方法 public void setCommonDao(ICommonDao commonDao) { this.commonDao = commonDao; } public void add(){ commonDao.add(); } }
dao層接口:
package com.spring.dao; public interface ICommonDao { public void add(); }
實現類:
package com.spring.dao.impl; import com.spring.dao.ICommonDao; public class CommonDaoImpl implements ICommonDao{ public void add(){ System.out.println("enter add!"); } }
配置文件:
<bean id="commonDao" class="com.spring.dao.impl.CommonDaoImpl"></bean> <bean id="commonService" class="com.spring.service.impl.CommonServiceImpl"> <!-- 注入持久化訪問所需的DAO組件 --> <property name="commonDao" ref="commonDao"/> </bean>
以上是不使用注解的方式注入依賴對象(使用屬性注入),下面來看一下使用注解為某個bean注入依賴對象。
(1)首先,在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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd "> </beans>
注意:只有配置了紫色部分的行才可以引入注解的命名空間,否則報錯。以上的配置隱式的注冊了多個對注釋進行解析的處理器:AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor等。
(2)其次,在配置文件中打開<context:annotation-config>節點,告訴Spring容器可以用注解的方式注入依賴對象;其在配置文件中的代碼如下:
<beans> …… <context:annotation-config></context:annotation-config> …… </beans>
(3)第三,在配置文件中配置bean對象,如下:
<bean id="commonDao" class="com.spring.dao.impl.CommonDaoImpl"></bean> <bean id="commonService" class="com.spring.service.impl.CommonServiceImpl"></bean>
(4)第四,在需要依賴注入的類中(本例中是CommonServiceImpl),聲明一個依賴對象,不用生成該依賴對象的setter方法,並且為該對象添加注解。
修改業務層實現類CommonServiceImpl
package com.spring.service.impl; import javax.annotation.Resource; import com.spring.dao.ICommonDao; import com.spring.service.ICommonService; public class CommonServiceImpl implements ICommonService{ @Resource(name="commonDao") private ICommonDao commonDao; // // 依賴注入DAO組件所需的setter方法 // public void setCommonDao(ICommonDao commonDao) { // this.commonDao = commonDao; // } public void add(){ commonDao.add(); } }
其中,在Java代碼中可以使用@Autowired或@Resource注解方式進行Spring的依賴注入。兩者的區別是:@Autowired默認按類型裝配,@Resource默認按名稱裝配,當找不到與名稱匹配的bean時,才會按類型裝配。
比如:我們用@Autowired為上面的代碼ICommonDao接口的實例對象進行注解,它會到Spring容器中去尋找與ICommonDao對象相匹配的類型,如果找到該類型則將該類型注入到commonDao字段中;
如果用@Resource進行依賴注入,它先會根據指定的name屬性去Spring容器中尋找與該名稱匹配的類型,例如:@Resource(name="commonDao"),如果沒有找到該名稱,則會按照類型去尋找,找到之后,會對字段commonDao進行注入。
使用注解注入依賴對象不用再在代碼中寫依賴對象的setter方法或者該類的構造方法,並且不用再配置文件中配置大量的依賴對象,使代碼更加簡潔,清晰,易於維護。
在Spring IOC編程的實際開發中推薦使用注解的方式進行依賴注入。
二、依賴注入——自動裝配
在應用中,我們常常使用<ref>標簽為JavaBean注入它依賴的對象,同時也Spring為我們提供了一個自動裝配的機制,在定義Bean時,<bean>標簽有一個autowire屬性,我們可以通過指定它來讓容器為受管JavaBean自動注入依賴對象。
自動裝配是在配置文件中實現的,如下:<bean id="***" class="***" autowire="byType">
只需要配置一個autowire屬性即可完成自動裝配,不用再配置文件中寫<property>,但是在類中還是要生成依賴對象的setter方法。
<bean>的autowire屬性有如下六個取值,他們的說明如下
1.No:即不啟用自動裝配。Autowire默認的值。默認情況下,需要通過"ref"來裝配bean,如下:
package com.lei.common; public class Customer { private Person person; public Customer(Person person) { this.person = person; } public void setPerson(Person person) { this.person = person; } //... }
package com.lei.common; public class Person { //... }
配置文件:
<bean id="customer" class="com.lei.common.Customer"> <property name="person" ref="person" /> </bean> <bean id="person" class="com.lei.common.Person" />
2.byName:按名稱裝配 可以根據屬性的名稱在容器中查詢與該屬性名稱相同的bean,如果沒有找到,則屬性值為null。假設Boss類中有一個名為car的屬性,如果容器中剛好有一個名為car的Bean,Spring就會自動將其裝配給Boss的car屬性。
根據屬性Property的名字裝配bean,這種情況,Customer設置了autowire="byName",Spring會自動尋找與屬性名字“person”相同的bean,找到后,通過調用setPerson(Person person)將其注入屬性。
<bean id="customer" class="com.lei.common.Customer" autowire="byName" /> <bean id="person" class="com.lei.common.Person" />
如果根據 Property name找不到對應的bean配置,如下:
<bean id="customer" class="com.lei.common.Customer" autowire="byName" /> <bean id="person_another" class="com.lei.common.Person" />
Customer中Property名字是person,但是配置文件中找不到person,只有person_another,這時就會裝配失敗,運行后,Customer中person=null。
3.byType:按類型裝配 可以根據屬性類型,在容器中尋找該類型匹配的bean,如有多個,則會拋出異常,如果沒有找到,則屬性值為null。假設Boss類中有一個Car類型的屬性,如果容器中剛好有一個Car類型的Bean,Spring就會自動將其裝配給Boss的這個屬性。
根據屬性Property的數據類型自動裝配,這種情況,Customer設置了autowire="byType",Spring會總動尋找與屬性類型相同的bean,找到后,通過調用setPerson(Person person)將其注入。
<bean id="customer" class="com.lei.common.Customer" autowire="byType" /> <bean id="person" class="com.lei.common.Person" />
如果配置文件中有兩個類型相同的bean會怎樣呢?如下:
<bean id="customer" class="com.lei.common.Customer" autowire="byType" /> <bean id="person" class="com.lei.common.Person" /> <bean id="person_another" class="com.lei.common.Person" />
一旦配置如上,有兩種相同數據類型的bean被配置,將拋出UnsatisfiedDependencyException異常,見以下:
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException:
所以,一旦選擇了“byType”類型的自動裝配,請確認你的配置文件中每個數據類型定義一個唯一的bean。
4.constructor:與byType方式相似,不同之處在與它應用於構造器參數,如果在容器中沒有找到與構造器參數類型一致的bean,那么將拋出異常。(根據構造函數參數的數據類型,進行byType模式的自動裝配。)
這種情況下,Spring會尋找與參數數據類型相同的bean,通過構造函數public Customer(Person person)將其注入。
<bean id="customer" class="com.lei.common.Customer" autowire="constructor" /> <bean id="person" class="com.lei.common.Person" />
5.autodetect:通過bean類的自省機制(introspection)來決定是使用constructor還是byType的方式進行自動裝配。如果Bean有空構造器那么將采用“byType”自動裝配方式,否則使用“constructor”自動裝配方式。
這種情況下,Spring會先尋找Customer中是否有默認的構造函數,如果有相當於上邊的"constructor"這種情況,用構造函數注入,否則,用"byType"這種方式注入,所以,此例中通過調用public Customer(Person person)將其注入。
<bean id="customer" class="com.lei.common.Customer" autowire="autodetect" /> <bean id="person" class="com.lei.common.Person" />
6.default:由上級標簽<beans>的default-autowire屬性確定。
注意:在配置bean時,<bean>標簽中Autowire屬性的優先級比其上級標簽高,即是說,如果在上級標簽中定義default-autowire屬性為byName,而在<bean>中定義為byType時,Spring IoC容器會優先使用<bean>標簽的配置。
小結:使用自動裝配,配置文件簡潔了許多。但是,自動裝配並不是十全十美的,我們不論是使用byName還是byType的方法,Spring不一定就能很准確的為我們找到JavaBean依賴的對象。在這種情況下,你務必遵守javabean的命名規范,另外,如果使用自動裝配,Spring配置文件的可讀性也大大降低,我們不能很容易的看出個bean之間的依賴關系,這也在一定程度上降低了程序可維護性;也容易造成潛在的錯誤,比如說通過byName來裝配,如果將屬性 名字改了后,Spring就不會將其自動裝配給Bean的屬性了。
因此在使用自動裝配時,應當權衡利弊,合理的與ref的方法相結合,盡量在降低工作量的同時,保證應用的可維護度。但是spring的reference還是不推薦在定義中用這個功能。
不是所有類型都能自動裝配,不能自動裝配的數據類型:Object、基本數據類型(Date、CharSequence、Number、URI、URL、Class、int)等。
三、注入參數詳解
·注入常量
注入常量是依賴注入中最簡單的。配置方式如下所示:
<property name="message" value="Hello World!"/> 或 <property name="index"><value>1</value></property>
以上兩種方式都可以,從配置來看第一種更簡潔。注意此處“value”中指定的全是字符串,由Spring容器將此字符串轉換成屬性所需要的類型,如果轉換出錯,將拋出相應的異常。
·注入集合類型
Java.util包中的集合類是最常用的數據結構類型,主要包括List、Set、Map、Properties,Spring為這些集合類型屬性提供了專門的配置元素標簽。
1.List:需要使用<list>標簽來配置注入。
新建一個Boss類,並在類中添加一個List類型的favorites屬性。
package com.spring.model; import java.util.List; public class Boss { private List favorites; public List getFavorites() { return favorites; } public void setFavorites(List favorites) { this.favorites = favorites; } public void print(){ System.out.println(favorites); } }
對應Spring中的配置片段如下所示:
<!-- 注入List類型屬性 --> <bean id="boss" class="com.spring.model.Boss"> <property name="favorites"> <list> <value>看報</value> <value>賽車</value> <value>高爾夫</value> </list> </property> </bean>
List屬性既可以通過<value>注入字符串,也可以通過<ref>注入容器中的其他Bean。
2.Set:需要使用<set>標簽來配置注入,其配置參數及含義和<lsit>標簽完全一樣,具體配置例子如下:
<bean id=”……” class=”……”> <property name="……"> <set> <value>value1</value> <value>value2</value> …… </set> </property> </bean>
3.Map:需要使用<map>標簽來配置注入,其屬性“key-type”和“value-type”分別指定“鍵”和“值”的數據類型。
在Boss類中添加一個Map類型的jobs屬性。
package com.spring.model; import java.util.List; import java.util.Map; public class Boss { private Map jobs; public Map getJobs() { return jobs; } public void setJobs(Map jobs) { this.jobs = jobs; } public void print1(){ System.out.println(jobs); } }
在配置文件中可以通過以下方式為jobs屬性提供配置值。
<!-- 注入Map類型屬性 --> <bean id="boss1" class="com.spring.model.Boss"> <property name="jobs"> <map> <entry key="AM" value="會見客戶" /> <entry key="PM" value="公司內部會議" /> </map> </property> </bean>
其中<map>表示Map注入,<entry>表示鍵值對,<key>表示鍵數據,<value>表示鍵所對應的值數據。
4.Properties:需要使用<props>標簽來配置注入,鍵和值類型必須是String,不能變,子標簽<prop key=”鍵”>值</prop>來指定鍵值對。
Properties類型其實可以看成是Map類型的特例。Map元素的鍵和值可以是任何類型的對象,而Properties屬性的鍵和值都只能是字符串。為Boss添加一個Properties類型的mails屬性。
package com.spring.model; import java.util.List; import java.util.Map; import java.util.Properties; public class Boss { private Properties mails; public Properties getMails() { return mails; } public void setMails(Properties mails) { this.mails = mails; } public void print2(){ System.out.println(mails); } }
下面的配置片段為mails提供了配置。
<!-- 注入Properties類型屬性 --> <bean id="boss2" class="com.spring.model.Boss"> <property name="mails"> <props> <prop key="jobMail">john-office@163.com</prop> <prop key="lifeMail">john-life@163.com</prop> </props> </property> </bean>
因為Properties鍵值對只能是字符串,因此其配置比Map的配置要簡單一些,注意值得配置沒有<value>子元素標簽。
·引用其他Bean
Spring IOC容器中定義的Bean可以相互引用,IOC容器則充當“紅娘”的角色。下面在Boss類中添加一個Car類型的屬性。
package com.spring.model; import java.util.List; import java.util.Map; import java.util.Properties; public class Boss { private Car car; //設置car屬性 public void setCar(Car car) { this.car = car; } public void print3(){ System.out.println(car.getBrand()+"----"+car.getPrice()+"----"+car.getMaxSpeed()); } }
boss的Bean通過<ref>元素引用car Bean,建立起boss對car的依賴。
<bean id="car" class="com.spring.model.Car"> <property name="maxSpeed" value="200"></property> <property name="brand" value="紅旗CA72"></property> <property name="price" value="200000.00"></property> </bean> <!-- 通過ref元素引用bean --> <bean id="boss3" class="com.spring.model.Boss"> <property name="car"> <!--引用上面定義的car Bean--> <ref bean="car"></ref> </property> </bean>
<ref>元素可以通過以下3個屬性引用容器中的其他Bean。
· bean:通過該屬性可以引用同一容器或父容器的Bean,這是最常見的形式。
· local:通過該屬性只能引用同一配置文件中定義的Bean,它可以利用XML解析器自動檢驗引用的合法性,以便在開發編寫配置時能夠及時發現並糾正配置的錯誤。
· parent:引用父容器中的Bean,如<ref parent="car">的配置說明car的Bean是父容器中的Bean。
為了說明子容器對父容器中Bean的引用,來看一個具體的例子。假設有兩個配置文件beans1.xml和beans2.xml,其中beans1.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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd "> <!--在父容器中定義的car --> <bean id="car" class="com.spring.model.Car"> <property name="brand" value="紅旗CA72"></property> <property name="maxSpeed" value="200"></property> <property name="price" value="200000.00"></property> </bean> </beans>
而beans2.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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd "> <!--1.該Bean和父容器中的car Bean具有相同的id --> <bean id="car" class="com.spring.model.Car"> <property name="brand" value="吉利CT5"></property> <property name="maxSpeed" value="100"></property> <property name="price" value="100000.00"></property> </bean> <bean id="boss" class="com.spring.model.Boss"> <property name="car"> <!--引用父容器中的car,而非1處定義的Bean,如果采用<ref bean="car" />將引用本容器1處的car --> <ref parent="car"></ref> </property> </bean> </beans>
在beans1.xml中配置了一個car Bean,在beans2.xml中也配置了一個car Bean。分別通過父子容器加載beans1.xml和beans2.xml,beans2.xml中的boss通過<ref parent="car">將引用到父容器中的car。下面是分別加載beans1.xml和beans2.xml配置文件的代碼。
/** * 引用父容器中的bean */ @Test public void test9(){ //父容器 ApplicationContext pFactory=new ClassPathXmlApplicationContext("beans1.xml"); //指定pFactory為該容器的父容器 ApplicationContext factory=new ClassPathXmlApplicationContext(new String[]{"beans2.xml"},pFactory); Boss boss=(Boss) factory.getBean("boss"); System.out.println("引用父容器中的bean"); System.out.println(boss.getCar().toString()); }
運行這段代碼,控制台中打印出以下的信息。
引用父容器中的bean
brand:紅旗CA72/maxSpeed:200/price:200000.0
