官术网_书友最值得收藏!

3.3 Bean的注入

在Bean的配置中介紹的是Bean的聲明問題,即在哪聲明、怎么聲明的問題。本節(jié)將要講解的Bean的注入是怎么實例化、怎么注入的問題。Bean注入的方式有兩種:一種是在XML中配置,另一種是使用注解的方式注入。

3.3.1 XML方式注入

XML方式注入一般有三種方式:屬性注入、構(gòu)造函數(shù)注入和工廠方法注入。

1.屬性注入

在傳統(tǒng)的對象實例化時可以先使用new class(),然后通過setXXX()方法設(shè)置對象的屬性值或依賴對象,屬性注入也是采用這種方式,只是Spring框架會在內(nèi)部完成這些操作,它會先調(diào)用Bean的默認(rèn)構(gòu)造函數(shù)實例化Bean對象,然后通過反射的方式調(diào)用Setter方法注入屬性值。它會使用默認(rèn)的構(gòu)造函數(shù)(無參數(shù)構(gòu)造函數(shù)),只需為注入的屬性設(shè)置set方法,可選擇性和靈活性比較高,所以也是比較常用的一種注入方式。這里還是在IOC章節(jié)人和空氣的基礎(chǔ)上稍作修改來演示。IAir接口和CleanAir、DirtyAir類不變,這里就不貼了。

(1)新建XMLInstance類

在XMLInstance類中并未聲明構(gòu)造函數(shù),對于air屬性只設(shè)置了set方法,get方法也沒設(shè)置。

在XML中使用property類配置屬性,name表示屬性名,value用來設(shè)置基本數(shù)據(jù)類型的屬性值。在Spring配置文件中,bean之間可以相互引用,引用時可以用<ref>標(biāo)簽配置bean的id屬性。<ref>可以用在<property>屬性中,也可以用在<construct-arg>構(gòu)造函數(shù)的參數(shù)值中,還可以用在其他地方,通過引用能減少bean的聲明。

2.構(gòu)造函數(shù)注入

在屬性注入時先使用默認(rèn)的構(gòu)造函數(shù)(無參數(shù)構(gòu)造函數(shù))實例化,然后通過set方法注入屬性,在傳統(tǒng)實例化對象時可以自定義構(gòu)造函數(shù)進(jìn)行實例化。構(gòu)造函數(shù)注入就是通過自定義構(gòu)造函數(shù)來進(jìn)行對象的實例化。這里在XMLInstance類的基礎(chǔ)上增加了一個構(gòu)造函數(shù),第一個參數(shù)是String類型的name,第二個參數(shù)是IAir類型的air。

在XML中,使用<construect-arg>來設(shè)置構(gòu)造函數(shù)的參數(shù),index屬性設(shè)置參數(shù)的順序,參數(shù)順序應(yīng)該與構(gòu)造函數(shù)一致,ref設(shè)置引用bean的id,value設(shè)置構(gòu)造函數(shù)參數(shù)的值。

3.工廠方法注入

工廠方法注入?yún)⒖嫉氖枪S設(shè)計模式,在工廠類中實現(xiàn)對象的實例化。工廠類負(fù)責(zé)創(chuàng)建一個或多個目標(biāo)類實例,一般以接口或抽象類變量的形式返回目標(biāo)類實例。工廠類對外屏蔽了目標(biāo)類的實例化步驟,調(diào)用者甚至不用知道具體的目標(biāo)類是什么。工廠方法也分靜態(tài)工廠方法和非靜態(tài)工廠方法。靜態(tài)工廠方法不用實例化工廠類,直接通過類名調(diào)用。非靜態(tài)工廠方法需要先實例化工廠類,然后通過工廠類對象調(diào)用獲取對象。這里創(chuàng)建了一個工廠類XMLFactory,在類中定義了一個靜態(tài)方法和一個實例方法(用來實例化bean對象)。

(1)靜態(tài)工廠方法

只需設(shè)置工廠方法對應(yīng)的類,以及對應(yīng)的工廠方法。

 <bean id="xmlfactorystaticinstance" class="com.demo.model.XMLFactory"
 factory-method="CreateStaticInstance"></bean>

(2)實例工廠方法

需要先實例化工廠類,再通過工廠類對象調(diào)用實例方法獲取bean對象。

 <bean id="xmlfactory" class="com.demo.model.XMLFactory"></bean>
 <bean id="xmlfactoryinstance" factory-bean="xmlfactory"
factory-method="CreateInstance"></bean>

4.常見數(shù)據(jù)類型注入

(1)List屬性注入

使用<list>配置java.util.List類型的屬性。List屬性中的元素可以是任何數(shù)據(jù)類型的值,如果是Java對象,可以使用ref指定,或使用<bean>定義新實例。如果是基礎(chǔ)數(shù)據(jù)類型,可直接使用字符串。<list>中的元素會按配置的先后順序排序。

(2)Set屬性注入

使用<set>配置java.util.Set類型的屬性。Set屬性中的元素可以是任何數(shù)據(jù)類型的值,如果是Java對象,可以使用ref指定,或使用<bean>定義新實例。如果是基礎(chǔ)數(shù)據(jù)類型,可直接使用字符串。<set>中的元素沒有先后順序。

(3)Map屬性注入

使用<map>配置java.util.Map類型的屬性。<entry>配置Map里的元素,key指定索引,value指定值。如果是Java對象,可以使用ref指定,或使用<bean>定義新實例。

(4)Properties屬性注入

使用<props>配置java.util.Properties類型的屬性。<props>配置一個Properties對象,<prop>配置一條屬性,屬性key配置索引。

(5)自定義屬性編輯器

有一些屬性是沒法注入的,此時就需要自定義,比如日期類型。可以通過繼承PropertyEditorSupport的類,重寫setAsText方法來實現(xiàn)注入。這里定義了CustomerProperty繼承PropertyEditorSupport,重寫了setAsText方法,并將該bean配置到XML中。

配置之后就可以注入Date類型的屬性了。

 <property name="date" value="2018-8-20"/>

新建XmlCollectionsDemo類,配置上面幾個類型的屬性來演示。

下面是屬性對應(yīng)的XML配置文件。

通過運行main方法,打印出屬性值:

     [1, CleanAir, CleanAir]
     {prokey2=prokeyB, prokey1=prokeyA}
     [1, CleanAir, CleanAir]
     {key1=1, key2=CleanAir, key3=CleanAir}
     Mon Aug 20 00:00:00 CST 2018

5.初始化函數(shù)、銷毀函數(shù)

通過上面幾種注入方式的學(xué)習(xí),對通過XML對bean實例化有了了解。有的對象在實例化之后還需要執(zhí)行某些初始化代碼,但這些初始化代碼還不能寫在構(gòu)造函數(shù)中,此時可以將初始化代碼寫到某個方法中。將init-method屬性值設(shè)置為該方法,Spring會強制執(zhí)行該方法進(jìn)行初始化。有的對象在使用完畢之后需要釋放,可以使用destroy-method來進(jìn)行銷毀。

這里先在XMLInstance類中增加上面兩個方法來模擬銷毀和初始化方法,然后在xml配置bean時設(shè)置destroy-method、init-method屬性值對應(yīng)兩個方法的方法名。注解中的@PostConstruct對應(yīng)init-method、@PreDestory對應(yīng)destroy-method。

 <bean id="xmlfactoryinstance" factory-bean="xmlfactory" factory-method=
"CreateInstance" destroy-method="DestoryMethod" init-method="InitMethod">
</bean>

3.3.2 注解方式注入

1.常用注解介紹

學(xué)習(xí)完XML注入之后再學(xué)習(xí)注解方式注入就容易得多了,注解方式注入主要涉及@Autowired、@Resource、@Required、@Qualifier、@Value這幾個注解。在2.2.4節(jié)定義Person時就使用過@Autowired、@Qualifier。下面來了解一下它們的具體用法。

● @Autowired:默認(rèn)按類型匹配注入bean,可以對類成員變量、方法及構(gòu)造函數(shù)進(jìn)行標(biāo)注,完成自動裝配的工作。在使用@Autowired時,首先在容器中查詢對應(yīng)類型的bean。如果查詢結(jié)果剛好為一個,就將該bean裝配給@Autowired指定的數(shù)據(jù);如果查詢的結(jié)果不止一個,那么@Autowired會根據(jù)名稱來查找。如果查詢的結(jié)果為空,那么會拋出異常。解決方法時,使用required=false。

● @Required:適用于bean屬性setter方法,并表示受影響的bean屬性必須在XML配置文件在配置時進(jìn)行填充;否則,容器會拋出一個BeanInitializationException異常。

● @Qualifier:@Autowired默認(rèn)是單實例的,但是在面向接口編程中,如果把一個屬性設(shè)置為接口類型,一個接口就可能有多個實現(xiàn),那么到底注入哪一個呢?為了解決這個問題,就有了@Qualifier。

● @Value:在xml配置屬性時可以通過property的value設(shè)置默認(rèn)值,@Value也可以為屬性設(shè)置默認(rèn)值。

● @Resource:默認(rèn)按名稱匹配注入bean。要求提供一個bean名稱的屬性,如果屬性為空,就自動采用標(biāo)注處的變量名或方法名作為bean的名稱。如果我們沒有在使用@Resource時指定bean的名字,同時Spring容器中又沒有該名字的bean,這時@Resource就會退化為@Autowired,即按照類型注入。

在上面的代碼中,使用@Value注解為name設(shè)置了默認(rèn)值,使用@Resources設(shè)置bean的名稱為IAir屬性注入bean,也可以使用@Autowired+@Qualifier為IAir注入bean。

2.開啟注解

配置完注解之后,還要告訴Spring開啟注解,這樣@Autowired、@Resources這些注解才起作用。開啟注解有兩種比較簡單的方式。

(1)在xml配置文件中使用context:annotation-config:

 <context:annotation-config />

(2)在xml配置文件中使用context:component-scan:

 <context:component-scan base-package="com.demo.model"/>
主站蜘蛛池模板: 崇阳县| 靖州| 台州市| 广灵县| 甘孜县| 贵阳市| 兴文县| 贵港市| 资中县| 金塔县| 色达县| 兰西县| 乡城县| 星子县| 新河县| 万载县| 海伦市| 永修县| 崇信县| 金山区| 汉中市| 隆化县| 巴楚县| 博客| 根河市| 西藏| 凤台县| 宁蒗| 海门市| 德化县| 彭山县| 隆回县| 翼城县| 榆林市| 芷江| 剑河县| 彭水| 丹巴县| 枣强县| 仪陇县| 敖汉旗|