Spring中bean有三種裝配機制,分別是:java
這裏咱們主要講第三種:自動化的裝配bean。git
Spring的自動裝配須要從兩個角度來實現,或者說是兩個操做:spring
組件掃描和自動裝配組合發揮巨大威力,使得顯示的配置下降到最少。測試
推薦不使用自動裝配xml配置 , 而使用註解 。ui
public class Cat { public void shout() { System.out.println("miao~"); } }
public class Dog { public void shout() { System.out.println("wang~"); } }
public class User { private Cat cat; private Dog dog; private String str; public Cat getCat() { return cat; } public Dog getDog() { return dog; } public String getStr() { return str; } public void setCat(Cat cat) { this.cat = cat; } public void setDog(Dog dog) { this.dog = dog; } public void setStr(String str) { this.str = str; } }
<?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="pojo.Dog"/> <bean id="cat" class="pojo.Cat"/> <bean id="user" class="pojo.User"> <property name="cat" ref="cat"/> <property name="dog" ref="dog"/> <property name="str" value="zc"/> </bean> </beans>
@Test public void Test(){ ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); User user = (User) context.getBean("user"); user.getCat().shout(); user.getDog().shout(); }
因爲在手動配置xml過程當中,經常發生字母缺漏和大小寫等錯誤,而沒法對其進行檢查,使得開發效率下降。this
採用自動裝配將避免這些錯誤,而且使配置簡單化。指針
修改bean配置:autowire="byName"code
<bean id="user" class="pojo.User" autowire="byName"> <property name="str" value="zc"/> </bean>
再次測試,一切正常。component
可是若是將 cat 的bean id修改成 catXXX,就會出現java.lang.NullPointerException
xml
由於按byName規則找不對應set方法,真正的setCat就沒執行,對象就沒有初始化,因此調用時就會報空指針錯誤。
當一個bean節點帶有 autowire byName的屬性時。
使用autowire byType首先須要保證:同一類型的對象,在spring容器中惟一。
修改bean配置:autowire="byType"
<bean id="user" class="pojo.User" autowire="byType"> <property name="str" value="zc"/> </bean>
再次測試,一切正常。
可是若是添加一個Cat的bean:
<bean id="cat1" class="pojo.Cat"/>
會報錯:NoUniqueBeanDefinitionException
,因此同一類型的對象,在spring容器中必須惟一。
綜上:
byName
: 須要保證全部的bean的id惟一,而且這個bean須要和自動注入的屬性的set的方法的值一致!byType
: 須要保證全部的bean的class惟一,而且這個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" 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"> </beans>
<context:annotation-config/>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.3.3</version> </dependency>
將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; } }
<?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 https://www.springframework.org/schema/context/spring-context.xsd "> <bean id="dog" class="pojo.Dog"/> <bean id="cat" class="pojo.Cat"/> <bean id="user" class="pojo.User"/> <context:annotation-config/> </beans>
測試,同樣成功。
@Autowired(required=false)
false:對象能夠爲null;
true:對象必須存對象,不能爲null。
<?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 https://www.springframework.org/schema/context/spring-context.xsd "> <bean id="dog" class="pojo.Dog"/> <bean id="dog1" class="pojo.Dog"/> <bean id="cat" class="pojo.Cat"/> <bean id="cat1" class="pojo.Cat"/> <bean id="user" class="pojo.User"/> <context:annotation-config/> </beans>
沒有加Qualifier測試,直接報錯
這時候,在屬性上添加Qualifier註解:
@Autowired @Qualifier(value = "cat") private Cat cat; @Autowired @Qualifier(value = "dog") private Dog dog; private String str;
測試,成功輸出。
實體類
public class User { @Resource(name = "cat") private Cat cat; @Resource private Dog dog; private String str; }
bean.xml
<bean id="dog" class="pojo.Dog"/> <bean id="cat" class="pojo.Cat"/> <bean id="cat1" class="pojo.Cat"/> <bean id="user" class="pojo.User"/>
測試經過
bean.xml
<bean id="dog" class="com.kuang.pojo.Dog"/> <bean id="cat" class="com.kuang.pojo.Cat"/>
實體類只保留註解
@Resource private Cat cat; @Resource private Dog dog;
測試經過
@Autowired與@Resource異同:
一、@Autowired與@Resource均可以用來裝配bean。均可以寫在字段上,或寫在setter方法上。
二、@Autowired默認按類型裝配(屬於spring規範),默認狀況下必需要求依賴對象必須存在,若是要容許null 值,能夠設置它的required屬性爲false,如:@Autowired(required=false) ,若是咱們想使用名稱裝配能夠結合@Qualifier註解進行使用
三、@Resource(屬於J2EE復返),默認按照名稱進行裝配,名稱能夠經過name屬性進行指定。若是沒有指定name屬性,當註解寫在字段上時,默認取字段名進行按照名稱查找,若是註解寫在setter方法上默認取屬性名進行裝配。當找不到與名稱匹配的bean時才按照類型進行裝配。可是須要注意的是,若是name屬性一旦指定,就只會按照名稱進行裝配。
它們的做用相同都是用註解方式注入對象,但執行順序不一樣。@Autowired先byType,@Resource先byName。