您好,登錄后才能下訂單哦!
首先,要學(xué)習(xí)Spring中的Bean的注入方式,就要先了解什么是依賴注入。依賴注入是指:讓調(diào)用類對某一接口的實(shí)現(xiàn)類的實(shí)現(xiàn)類的依賴關(guān)系由第三方注入,以此來消除調(diào)用類對某一接口實(shí)現(xiàn)類的依賴。
Spring容器中支持的依賴注入方式主要有屬性注入、構(gòu)造函數(shù)注入、工廠方法注入。接下來將為大家詳細(xì)介紹這三種依賴注入的方式以及它們的具體配置方法。
1.屬性注入
屬性注入即通過setXXX( )方法注入bean的屬性值或依賴對象。由于屬性注入方式具有可選擇性和靈活性高的特點(diǎn),因此它也是實(shí)際開發(fā)中最常用的注入方式。
Spring首先會(huì)調(diào)用bean的默認(rèn)構(gòu)造函數(shù)實(shí)例化bean對象,然后再通過反射的方法調(diào)用set方法來注入屬性值。
屬性注入要求bean提供一個(gè) 默認(rèn)的構(gòu)造函數(shù) ,并且得為需要注入的屬性提供 set方法 。
TIps:所謂默認(rèn)的構(gòu)造函數(shù),即不帶參數(shù)的構(gòu)造函數(shù)。如果類中沒有自定義任何構(gòu)造函數(shù),則系統(tǒng)(JVM)會(huì)自動(dòng)生成一個(gè)不帶參的默認(rèn)構(gòu)造函數(shù),如果類中顯式的自定義了有參數(shù)的構(gòu)造函數(shù),則系統(tǒng)就不會(huì)在自動(dòng)生成默認(rèn)構(gòu)造函數(shù),需要自己手動(dòng)再加一個(gè)無參的構(gòu)造函數(shù)。
下面通過一個(gè)實(shí)例來演示Spring中bean的屬性注入方式:
編寫一個(gè)user類:
package com.Kevin.bean; /** * 創(chuàng)建一個(gè)類測試bean的屬性注入方式 * @author Kevin * */ public class User { private String username; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } }
配置文件:
<?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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here --> <!-- 配置對象 --> <bean id="user" class="com.Kevin.bean.User"> <property name="username"> <value>Kevin</value> </property> </bean> </beans>
其中,每個(gè)屬性值對應(yīng)一個(gè)property標(biāo)簽,name屬性值為類中屬性的名稱。在bean實(shí)現(xiàn)類中擁有與其對應(yīng)的實(shí)現(xiàn)方法setUsername( )。
Tips:Spring只會(huì)檢查bean中是否含有setter方法,而對是否有對應(yīng)的屬性變量則不作具體要求,但按照約定俗成的規(guī)則我們最好為其設(shè)定相應(yīng)的屬性變量。
Spring中<property>標(biāo)簽的命名規(guī)范:
一般情況下,java的屬性變量名都以小寫字母開頭,但考慮到一些特殊意義的英文縮略詞,java bean也允許一些大寫字母開頭的變量名。但必須滿足以下兩點(diǎn):
對于屬性注入方式來說,只能人為的在配置文件中提供保證,而無法在語法級別提供保證。此時(shí)就需要使用構(gòu)造函數(shù)注入這種方式,以此來更好的滿足要求。
2.構(gòu)造函數(shù)注入
構(gòu)造函數(shù)注入是除屬性注入之外的另一種常用的注入方式,它可以保證一些必要的屬性在bean實(shí)例化時(shí)就得到了設(shè)置,并在實(shí)例化后就可以使用。
使用構(gòu)造函數(shù)注入的前提是: bean必須提供帶參的構(gòu)造函數(shù)。
對于構(gòu)造函數(shù)的注入,配置文件可以有以下幾種方式:
【按類型匹配入?yún)⒎绞健?/strong>
編寫bean代碼:
package com.Kevin.bean; /** * 編寫bean測試按類型匹配入?yún)⒎绞? * @author Kevin * */ public class Person { private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
編寫配置文件:
<?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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here --> <!-- 配置對象 --> <bean id="person" class="com.Kevin.bean.Person"> <constructor-arg type="String"> <value>Kevin</value> </constructor-arg> <constructor-arg type="Integer"> <value>20</value> </constructor-arg> </bean> </beans>
Spring的配置文件采用和元素標(biāo)簽順序無關(guān)的配置策略,因此可以在一定程度上保證配置信息的確定性。
那么當(dāng)bean中的構(gòu)造函數(shù)的 多個(gè)類型參數(shù)一樣時(shí) ,按照類型匹配入?yún)⒌倪@種方式容易產(chǎn)生混淆,此時(shí)就需要使用另一種方式:按照索引匹配入?yún)ⅰ?/p>
【按照索引匹配入?yún)ⅰ?/strong>
編寫bean代碼:
package com.Kevin.bean; /** * 編寫bean測試按照索引方式入?yún)? * @author Kevin * */ public class Student { private String name; private String gender; private Double score; public Student(String name, String gender, Double score) { super(); this.name = name; this.gender = gender; this.score = score; } }
配置文件編寫如下:
<?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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here --> <!-- 配置對象 --> <bean id="student" class="com.Kevin.bean.Student"> <constructor-arg index="0" value="Kevin"></constructor-arg> <constructor-arg index="1" value="Male"></constructor-arg> <constructor-arg index="2" value="66"></constructor-arg> </bean> </beans>
Tips: 在屬性注入時(shí),Spring按java bean的規(guī)范確定配置 屬性 和對應(yīng)的 setter方法 ,并使用java反射機(jī)制調(diào)用屬性的setter方法完成屬性注入。但java反射機(jī)制并 不會(huì)記住構(gòu)造函數(shù)的入?yún)⒚?,因此我們不能通過制定構(gòu)造函數(shù)的入?yún)⒚Q來進(jìn)行構(gòu)造函數(shù)的配置,所以我們只能通過 入?yún)⒌念愋图八饕?來間接完成構(gòu)造函數(shù)的屬性注入。
【聯(lián)合使用類型和索引匹配入?yún)ⅰ?/strong>
在某些復(fù)雜的配置文件當(dāng)中,需要使用type和index同時(shí)出馬才能完成構(gòu)造函數(shù)的參數(shù)注入。下面使用一個(gè)實(shí)例來演示。
編寫bean:
package com.Kevin.bean; /** * 編寫bean測試聯(lián)合使用類型和索引匹配入?yún)? * @author Kevin * */ public class Teacher { private String name; private String address; private double salary; private int age; public Teacher(String name, String address, double salary) { super(); this.name = name; this.address = address; this.salary = salary; } public Teacher(String name, String address, int age) { super(); this.name = name; this.address = address; this.age = age; } }
在這個(gè)類中,有兩個(gè)重載的構(gòu)造函數(shù),他們都有三個(gè)參數(shù),在這種情況下使用type和index的方法都不能完成要求,這時(shí)候就需要他們兩個(gè)屬性同時(shí)使用了。
配置文件:
<?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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here --> <!-- 配置對象 --> <bean id="teacher" class="com.Kevin.bean.Teacher"> <constructor-arg index="0" type="String"> <value>Kevin</value> </constructor-arg> <constructor-arg index="1" type="String"> <value>China</value> </constructor-arg> <constructor-arg index="2" type="int"> <value>20</value> </constructor-arg> </bean> </beans>
可以看到其實(shí)重點(diǎn)在于第三個(gè)入?yún)⒌念愋?,所以我們在配置文件中指定了索引和類型,這樣便可以使得Spring知道對哪個(gè)構(gòu)造函數(shù)進(jìn)行參數(shù)注入了。
Tips: 加入我們得配置文件中存在歧義問題,Spring容器是可以正常啟動(dòng)的,并不會(huì)報(bào)錯(cuò),它將隨機(jī)采用一個(gè)匹配的構(gòu)造函數(shù)實(shí)例化bean。而隨機(jī)選擇的構(gòu)造函數(shù)可能并不是用戶所需要的,所以我們在編程時(shí)要小心避免出現(xiàn)這種歧義情況。
【通過自身類型反射匹配入?yún)ⅰ?/strong>
如果bean構(gòu)造函數(shù)入?yún)⒌念愋褪强杀鎰e的,由于java反射機(jī)制可以獲取構(gòu)造函數(shù)入?yún)⒌念愋?,即使?gòu)造函數(shù)的注入不提供類型和索引的信息,Spring依舊可以完成構(gòu)造函數(shù)信息的注入。例如下面實(shí)例中Manager類的構(gòu)造函數(shù)的入?yún)㈩愋途褪强梢员鎰e的。
編寫Manager類:
package com.Kevin.bean; /** * 編寫B(tài)ean測試通過自身類型反射匹配入?yún)⒎绞? * @author Kevin * */ public class Manager { private String name; private Double salary; private Person person; public Manager(String name, Double salary, Person person) { super(); this.name = name; this.salary = salary; this.person = person; } }
編寫配置文件:
<?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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here --> <!-- 配置對象 --> <bean id="manager" class="com.Kevin.bean.Manager"> <constructor-arg> <value>Kevin</value> </constructor-arg> <constructor-arg> <ref bean="user"/> </constructor-arg> <constructor-arg> <ref bean="person"/> </constructor-arg> </bean> </beans>
以上幾種方法都可以實(shí)現(xiàn) 構(gòu)造函數(shù)參數(shù)的注入 ,但是為了避免問題的發(fā)生,還是建議使用 顯式的index和type 來配置構(gòu)造函數(shù)的入?yún)⑿畔ⅰ?/p>
3.工廠方法注入
工廠方法是應(yīng)用中被經(jīng)常使用的設(shè)計(jì)模式,也是 控制反轉(zhuǎn) 和 單實(shí)例設(shè)計(jì)思想 的主要實(shí)現(xiàn)方法。工廠類負(fù)責(zé)創(chuàng)建一個(gè)或多個(gè)工廠類實(shí)例,工廠類方法一般以接口或抽象類變量的形式返回目標(biāo)類實(shí)例。
工廠類對外屏蔽了目標(biāo)類的實(shí)例化步驟,調(diào)用者甚至根本不用指定具體的目標(biāo)類是什么。由于Spring容器以框架的方法提供工廠方法的功能,并以透明的方式開放給開發(fā)者。因此很少需要手工編寫工程方法。但在一些遺留系統(tǒng)或第三方類庫中還是會(huì)碰到工程方法,此時(shí)便可以使用Spring工廠注入的方法來進(jìn)行Spring的注入。
Spring工廠注入的方法可以分為 靜態(tài) 和 非靜態(tài) 兩種。
【非靜態(tài)工廠方法】
有些工廠方法是非靜態(tài)的,必須實(shí)例化工廠類之后才能調(diào)用工廠方法。下面通過一個(gè)實(shí)例來演示。
編寫工廠類:
package com.Kevin.factorybean; /** * 編寫工廠類測試非靜態(tài)工廠方法注入 * @author Kevin * */ public class BookFactory { public Book buyBook(){ Book book = new Book(); book.setName("Think in Java"); return book; } }
配置文件編寫:
<?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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here --> <!-- 配置對象 --> <bean id="bookFactory" class="com.Kevin.factorybean.BookFactory"></bean> <bean id="book" factory-bean="bookFactory" factory-method="buyBook"></bean> </beans>
由于bookFactory的工廠方法不是靜態(tài)的,因此需要先定義一個(gè)工廠類的bean,然后通過 factory-bean 屬性來引用工廠bean實(shí)例。再通過屬性 factory-method 來指定對應(yīng)的工廠方法。
【靜態(tài)工廠方法】
很多工廠類方法都是靜態(tài)的,這意味著無需創(chuàng)建工廠類實(shí)例的情況下就可以調(diào)用工廠類方法。因此靜態(tài)工程方法比非靜態(tài)工廠方法的調(diào)用更加方便簡潔。下面通過一個(gè)實(shí)例來演示靜態(tài)工廠方法。
編寫factory類:
package com.Kevin.factorybean; /** * 編寫工廠類測試靜態(tài)工廠方法注入 * @author Kevin * */ public class CarFactory { public static Car createCar(){ Car car = new Car(); car.setBrand("Lamborghini"); return car; } }
編寫配置文件:
<?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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here --> <!-- 配置對象 --> <bean id="car" class="com.Kevin.factorybean.Car" factory-method="createCar"></bean> </beans>
總結(jié)
Spring提供了三種可供選擇的注入方式,但在實(shí)際應(yīng)用中,我們究竟該選擇哪種注入方式,并沒有統(tǒng)一的標(biāo)準(zhǔn),如下是一些可以參考的理由:
構(gòu)造函數(shù)注入理由:
屬性注入理由:
其實(shí)Spring為我們注入?yún)?shù)提供了這么多方法,那么這些方法必然有他們存在的道理,每個(gè)方法在某一問題上會(huì)有獨(dú)特的優(yōu)勢,我們只需要按照我們具體的使用需求選擇適合的方法來使用就好了,但一般不太推薦工廠方法注入。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。