基於註解自動裝配Bean
自動裝配(autowiring):有助於減少<property>和<constructor-arg>,讓spring自動識別如何裝配Bean的依賴關係。
自動檢測(autodiscovery):讓spring自動識別那個類要被裝配成spring Bean,減少對<bean>元素的使用。
1.自動裝配Bean屬性
1.1 4中型別的自動裝配
1.byName:把與Bean的屬性具有相同名字(或者ID)的其他Bean自動裝配到Bean的對應屬性中。如果沒有與屬性的名字相匹配的Bean,則該屬性不進行裝配。
2.byType:把與Bean的屬性具有相同型別的其他Bean自動裝配到Bean的對應屬性中。如果沒有與屬性的型別相匹配的Bean,則該屬性不進行裝配。
3.constructor:把與Bean的構造器入參具有相同型別的其他Bean自動裝配到Bean構造器的對應入參中。
4.autodetect:先按constructor來裝配,失敗了按byType來裝配。
1.1.1 byName自動裝配
<bean id="aaa" clas=""/>
<bean id="bbb" class="" >
<property name="aaa" ref="aaa"/>
</bean>
如果bbb中aaa屬性名字和Bean的id相同,則可以自動裝配。如果bean的id和property的name相同,那麼可以變為下面的這種方式:
<bean id="aaa" clas=""/>
<bean id="bbb" class="" autowire="byName">
</bean>
如果一個Bean中屬性和其他Bean的id相同就會自動裝配,可是自己不需要自動裝配。byName的缺點就是要假設屬性名和Bean的id要一樣。
1.1.2 byType自動裝配
跟byName一樣,只是ByType不去找屬性名一樣,而是去找屬性的型別。
<bean id="aaa" clas="A"/>
<bean id="bbb" class="" >
<property name="aaa" ref="aaa"/>
</bean>
如果bbb中屬性aaa為A型別,則可以byType自動裝配,把autowire="byType"
<bean id="aaa" clas="A"/>
<bean id="bbb" class="" autowire="ByType">
</bean>
如果byType找到多個Bean,那麼丟擲異常,應用只允許存在一個Bean與需要的自動裝配的屬性相匹配。byName不會找到多個,因為Bean的id是不一樣的。解決的辦法就是可以標識一個首選Bean,也可以讓其他Bean失去資格。<bean>元素有個primary屬性表示首選Bean,但是預設為true,所有的Bean都是首選Bean,所以要把非首選的Bean設定為false。<bean>的
autowire-candidate屬性可以設定為false表示自動裝備忽略Bean的資格。
1.1.3 constructor自動裝配
不需要<constructor-arg>元素,autowire為constructor。和byType有相同的侷限性,也是按照型別去匹配的,一個構造器引數對應多個Bean,還有一個Bean對應多個構造器。
1.2 預設自動裝配
如果所有的bean都按照同一型別自動裝配,可以再<beans>元素中加default-autowire屬性。這個屬性預設為none,表示不使用自動裝配。可以設定為byName等型別。<bean>中的autowire會覆蓋default-autowire屬性。<property>會覆蓋自動裝配的值。
autowire=“constructor”時,不能與<constructor-arg>同時存在。其他型別可以於<property>同時存在。
2. 使用註解裝配
spring容器是預設禁用註解裝配的。要啟動,最簡單的就是context名稱空間的<context:annotation-config/>
1.spring自帶的@Autowired註解2.JSR-330的@Inject註解
3.JSR-250的@Resource註解
2.1 @Autowired
有了這個註解,spring會按byType自動裝配。這個註解可以加在setter方法上,還可以加在需要自動裝配Bean的任意方法上,還可以加在構造器上。這個註解可以直接加在屬性上,並刪除setter方法。
這個註解必須只能有一個Bean匹配到註解的引數或屬性中。沒有匹配Bean或匹配多個Bean會有問題。
2.1.1可選的自動裝配
預設情況下,這個註解標識的屬性或引數必須是可裝配的。沒有Bean裝配到,就會報NoSuchBeanDefinitionException。這個時候可以設定required=false來設定自動裝配是可選的。沒有匹配到Bean就會為null。
@Autowired(required=false)
private A a;
required可以用於@Autowired使用的任何地方,但是在構造器中,只能有一個構造器是required為true,其他都要設定為false。當@Autowired標註多個構造器時,spring會從滿足條件的構造器中選擇入參最多的構造器。
2.1.2限定歧義性的依賴
有可能spring找到了多個滿足條件的Bean,可以使用@Qualifier註解。
@Autowired
@Qualifier("a")//指定a,預設從id找
private A a;
相當於把byType轉為了byName。縮小了自動裝配Bean的範圍。還可以在Bean中宣告
<bean class="A">
<qualifier value="a"/>//可以限定這個Bean為a
</bean>
@Qualifier("a")//可以限定這個Bean為a
class A implement B{}
@Autowired是減少spring xml配置的一種方式。但是使用它的類會引入spring的特定依賴。
2.2 @Inject
@Inject
private A a;
這個註解和@Autowired一樣可以自動裝配,可以裝配屬性,方法,構造器。但是沒有required屬性所以裝配的Bean必須存在,不存在會報錯。
2.2.1限定@Inject所標註的屬性
@Autowired的@Qualifier與@Inject的@Named對應
@Inject
@Named("a")
private A a;
@Qualifier註解縮小Bean的選擇範圍(預設使用Bean的id),@Named通過Bean的Id標識可選擇的Bean。2.3在註解注入中使用表示式
@Value可以裝配簡單值。
@Value("jack")//這裡面是一個表示式
private String name;
@Value("#{abc.name}")
private String name;
@Resource裝配順序
1. 如果同時指定了name和type,則從Spring上下文中找到唯一匹配的bean進行裝配,找不到則丟擲異常
2. 如果指定了name,則從上下文中查詢名稱(id)匹配的bean進行裝配,找不到則丟擲異常
3. 如果指定了type,則從上下文中找到型別匹配的唯一bean進行裝配,找不到或者找到多個,都會丟擲異常
4. 如果既沒有指定name,又沒有指定type,則自動按照byName方式進行裝配;如果沒有匹配,則回退為一個原始型別進行匹配,如果匹配則自動裝配;
<context:component-scan>除了完成<context:annotation-config>一樣的工作外,還允許Spring自動檢測Bean和定義Bean。
<context:component-scan//替代了<context:annotation-config>
base-package="包">//會掃描指定的包及其子包,並找出能夠自動註冊的spring Bean
</context:component-scan>
3.1為自動檢測標註Bean
預設情況下<context:component-scan>查詢使用構造型註解所標註的類。
[email protected]:通用的構造型註解,表示該類為spring元件
[email protected]:表示該類定義為spring mvc controller
[email protected]:表示該類為資料倉庫。
[email protected]:表示該類定義為服務
5.使用@Component標識的任意自定義註解
3.2過濾元件掃描
<context:component-scan>下面還有子元素<context:include-filter>和<context:exclude-filter>。只是用<context:component-scan>的情況下,spring只會去找基於註解的元件。但是還要包含一個沒有註解的介面的所有實現類要怎麼辦。就是用<context:include-filter>
<context:component-scan
base-package="包">
<context:include-filter type="assignable" expression="xxx.abc"/>
</context:component-scan>
type的5中型別
1.annotation:掃面指定註解所標註的類,通過expression指定註解。
2.assignable:掃面派生於expression指定型別的哪些類。
3.aspectj:掃面與expression指定的aspectJ表示式匹配的類
4.custom:指定expression使用的自定義TypeFilter實現類。
5.regex:正則匹配的類。
4 使用spring基於Java的配置
4.1 建立基於Java的配置
<context:component-scan>也會自動載入使用@Configuration註解所標註的類。
4.2 定義一個配置類
@Configurstion標註的類相當於<Beans>元素。可以包含一個或多個Bean。這些Bean的定義是使用@Bean註解來標註的方法。
4.3 宣告一個簡單Bean
@Bean
public A get(){
return new B();
}
@Bean告知spring返回一個物件,該物件應該被註冊為spring上下文的一個Bean。方法名為Bean的id。相對於xml配置來說的一個優點就是,xml是用string型別配置的,編譯期無法檢查。如果重新命名了一個類,或許會完了修改xml配置。
4.4 使用spring的基於Java的配置進行注入
簡單值注入:
@Bean
public A get(){
return new B(12);
}
@Bean
public A get(){
B b = new B();
b.setName("jack");
return B;
}
引用注入:
@Bean
public A get(){
return new B();
}
@Bean
public C set(){
return new C(get());
}
這裡呼叫get()不會呼叫get()方法而是呼叫spring上下文中的Bean。