1无午、自動(dòng)裝配說明
自動(dòng)裝配是使用spring滿足bean依賴的一種方法
spring會(huì)在應(yīng)用上下文中為某個(gè)bean尋找其依賴的bean恨胚。
Spring中bean有三種裝配機(jī)制,分別是:
- 在xml中顯式配置矾瑰;
- 在java中顯式配置坦敌;
- 隱式的bean發(fā)現(xiàn)機(jī)制和自動(dòng)裝配。
Spring的自動(dòng)裝配需要從兩個(gè)角度來實(shí)現(xiàn)希坚,或者說是兩個(gè)操作:
- 組件掃描(component scanning):spring會(huì)自動(dòng)發(fā)現(xiàn)應(yīng)用上下文中所創(chuàng)建的bean边苹;
- 自動(dòng)裝配(autowiring):spring自動(dòng)滿足bean之間的依賴,也就是我們說的IoC/DI裁僧;
組件掃描和自動(dòng)裝配組合發(fā)揮巨大威力个束,使得顯示的配置降低到最少慕购。
推薦不使用自動(dòng)裝配xml配置 , 而使用注解 .
2、測試環(huán)境搭建
1茬底、新建一個(gè)項(xiàng)目
2沪悲、新建兩個(gè)實(shí)體類,Cat Dog 都有一個(gè)叫的方法
public class Cat {
public void shout() {
System.out.println("miao~");
}
}
public class Dog {
public void shout() {
System.out.println("wang~");
}
3阱表、新建一個(gè)用戶類 User
public class User {
private Cat cat;
private Dog dog;
private String str;
}
4殿如、編寫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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="cat" class="com.kuang.pojo.Cat"/>
<bean id="user" class="com.kuang.pojo.User">
<property name="cat" ref="cat"/>
<property name="dog" ref="dog"/>
<property name="str" value="qinjiang"/>
</bean>
</beans>
5、測試
public class MyTest {
@Test
public void testMethodAutowire() {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user");
user.getCat().shout();
user.getDog().shout();
}
}
結(jié)果正常輸出最爬,環(huán)境OK
3涉馁、byName
autowire byName (按名稱自動(dòng)裝配)
由于在手動(dòng)配置xml過程中,常常發(fā)生字母缺漏和大小寫等錯(cuò)誤爱致,而無法對其進(jìn)行檢查烤送,使得開發(fā)效率降低。
采用自動(dòng)裝配將避免這些錯(cuò)誤蒜鸡,并且使配置簡單化胯努。
測試:
1、修改bean配置逢防,增加一個(gè)屬性 autowire="byName"
<bean id="user" class="com.nie.pojo.User" autowire="byName">
<property name="str" value="nie"/>
</bean>
2叶沛、再次測試,結(jié)果依舊成功輸出忘朝!
3灰署、我們將 cat 的bean id修改為 catXXX
4、再次測試局嘁, 執(zhí)行時(shí)報(bào)空指針java.lang.NullPointerException溉箕。因?yàn)榘碽yName規(guī)則找不對應(yīng)set方法,真正的setCat就沒執(zhí)行悦昵,對象就沒有初始化肴茄,所以調(diào)用時(shí)就會(huì)報(bào)空指針錯(cuò)誤。
小結(jié):
當(dāng)一個(gè)bean節(jié)點(diǎn)帶有 autowire byName的屬性時(shí)但指。
將查找其類中所有的set方法名寡痰,例如setCat,獲得將set去掉并且首字母小寫的字符串棋凳,即cat拦坠。
去spring容器中尋找是否有此字符串名稱id的對象。
如果有剩岳,就取出注入贞滨;如果沒有,就報(bào)空指針異常拍棕。
3晓铆、byType
autowire byType (按類型自動(dòng)裝配)
使用autowire byType首先需要保證:同一類型的對象勺良,在spring容器中唯一。如果不唯一尤蒿,會(huì)報(bào)不唯一的異常郑气。
NoUniqueBeanDefinitionException
測試:
1、將user的bean配置修改一下 : autowire="byType"
2腰池、測試尾组,正常輸出
3、在注冊一個(gè)cat 的bean對象示弓!
<bean id="dog" class="com.nie.pojo.Dog"/>
<bean id="cat" class="com.nie.pojo.Cat"/>
<bean id="cat2" class="com.nie.pojo.Cat"/>
<bean id="user" class="com.nie.pojo.User" autowire="byType">
<property name="str" value="nie"/>
</bean>
4讳侨、測試,報(bào)錯(cuò):NoUniqueBeanDefinitionException
5奏属、刪掉cat2跨跨,將cat的bean名稱改掉!測試囱皿!因?yàn)槭前搭愋脱b配勇婴,所以并不會(huì)報(bào)異常,也不影響最后的結(jié)果嘱腥。甚至將id屬性去掉耕渴,也不影響結(jié)果。
這就是按照類型自動(dòng)裝配
4齿兔、使用注解實(shí)現(xiàn)自動(dòng)裝配
jdk1.5開始支持注解橱脸,spring2.5開始全面支持注解。
1分苇、準(zhǔn)備工作
-
在spring配置文件中引入context文件
xmlns:context="http://www.springframework.org/schema/context" http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
-
開啟屬性注解支持添诉!
<context:annotation-config/>
-
匯總
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/> </beans>
@Autowired
- @Autowired是按類型自動(dòng)轉(zhuǎn)配的,不支持id匹配医寿。
- 需要導(dǎo)入 spring-aop的包栏赴!
測試:
1、將User類中的set方法去掉靖秩,使用@Autowired注解
public class User {
@Autowired
private Cat cat;
@Autowired
private Dog dog;
private String str;
public Cat getCat() {
return cat;
}
public Dog getDog() {
return dog;
}
public String getStr() {
return str;
}
2艾帐、此時(shí)配置文件內(nèi)容
<context:annotation-config/>
<bean id="dog" class="com.nie.pojo.Dog"/>
<bean id="cat" class="com.nie.pojo.Cat"/>
<bean id="user" class="com.nie.pojo.User"/>
3、測試盆偿,成功輸出結(jié)果!
@Autowired(required=false) 說明:false准浴,對象可以為null事扭;true,對象必須存對象乐横,不能為null求橄。
//如果允許對象為null今野,設(shè)置required = false,默認(rèn)為true
@Autowired(required = false)
private Cat cat;
@Qualifier
- @Autowired是根據(jù)類型自動(dòng)裝配的,加上@Qualifier則可以根據(jù)byName的方式自動(dòng)裝配
- @Qualifier不能單獨(dú)使用罐农。
測試實(shí)驗(yàn)步驟:
1条霜、配置文件修改內(nèi)容,保證類型存在對象涵亏。且名字不為類的默認(rèn)名字宰睡!
<bean id="dog1" class="com.nie.pojo.Dog"/>
<bean id="dog2" class="com.nie.pojo.Dog"/>
<bean id="cat1" class="com.nie.pojo.Cat"/>
<bean id="cat2" class="com.nie.pojo.Cat"/>
2、沒有加Qualifier測試气筋,直接報(bào)錯(cuò)
3拆内、在屬性上添加Qualifier注解
@Autowired
@Qualifier(value = "cat2")
private Cat cat;
@Autowired
@Qualifier(value = "dog2")
private Dog dog;
測試,成功輸出宠默!
@Resource
- @Resource如有指定的name屬性麸恍,先按該屬性進(jìn)行byName方式查找裝配;
- 其次再進(jìn)行默認(rèn)的byName方式進(jìn)行裝配搀矫;
- 如果以上都不成功抹沪,則按byType的方式自動(dòng)裝配。
- 都不成功瓤球,則報(bào)異常融欧。
實(shí)體類:
public class User {
//如果允許對象為null,設(shè)置required = false,默認(rèn)為true
@Resource(name = "cat2")
private Cat cat;
@Resource
private Dog dog;
private String str;
}
beans.xml
<bean id="dog" class="com.nie.pojo.Dog"/>
<bean id="cat1" class="com.nie.pojo.Cat"/>
<bean id="cat2" class="com.nie.pojo.Cat"/>
<bean id="user" class="com.nie.pojo.User"/>
測試:結(jié)果OK
配置文件2:beans.xml 冰垄, 刪掉cat2
<bean id="dog" class="com.nie.pojo.Dog"/>
<bean id="cat1" class="com.nie.pojo.Cat"/>
實(shí)體類上只保留注解
@Resource
private Cat cat;
@Resource
private Dog dog;
結(jié)果:OK
結(jié)論:先進(jìn)行byName查找蹬癌,失敗虹茶;再進(jìn)行byType查找逝薪,成功。
小結(jié)
@Autowired與@Resource異同:
1蝴罪、@Autowired與@Resource都可以用來裝配bean董济。都可以寫在字段上,或?qū)懺趕etter方法上要门。
2虏肾、@Autowired默認(rèn)按類型裝配(屬于spring規(guī)范),默認(rèn)情況下必須要求依賴對象必須存在欢搜,如果要允許null 值封豪,可以設(shè)置它的required屬性為false,如:@Autowired(required=false) 炒瘟,如果我們想使用名稱裝配可以結(jié)合@Qualifier注解進(jìn)行使用
3吹埠、@Resource(屬于J2EE復(fù)返),默認(rèn)按照名稱進(jìn)行裝配,名稱可以通過name屬性進(jìn)行指定缘琅。如果沒有指定name屬性粘都,當(dāng)注解寫在字段上時(shí),默認(rèn)取字段名進(jìn)行按照名稱查找刷袍,如果注解寫在setter方法上默認(rèn)取屬性名進(jìn)行裝配翩隧。當(dāng)找不到與名稱匹配的bean時(shí)才按照類型進(jìn)行裝配。但是需要注意的是呻纹,如果name屬性一旦指定堆生,就只會(huì)按照名稱進(jìn)行裝配。
它們的作用相同都是用注解方式注入對象居暖,但執(zhí)行順序不同顽频。@Autowired先byType,@Resource先byName太闺。