從Spring2.5開始就可以使用註解自動裝配Bean的屬性。使用註解自動裝配與XML中使用autowire屬性自動裝配並沒有太大差別。
Spring容器默認禁用註解裝配。所以在基於註解自動裝配,我們需要在Spring配置中啓用它。如:<context:annotation-config/>
<context:annotation-config/>他的作用是向Spring容器註冊
AutowiredAnnotationBeanPostProcessor(@Autowired)
CommonAnnotationBeanPostProcessor(@ Resource 、@ PostConstruct、@ PreDestroy等註解)
PersistenceAnnotationBeanPostProcessor(@PersistenceContext)
RequiredAnnotationBeanPostProcessor (@Required)
這四個BeanPostProcessor。
總是需要按照傳統的方式一條一條配置顯得有些繁瑣和沒有必要,於是spring給我們提供<context:annotation-config/>的簡化配置方式,自動幫你完成聲明。
Spring還有一個配置<context:component-scan base-package=”cn.com.xx.xx”/>能替代<context:annotation-config/>,我們後面在說。
@Autowired的使用
使用@Autowired我們得知道它是按照byType自動裝配的,可以無需寫set方法,甚至不會受限於private關鍵字。即使是私有實例變量,它仍然可以被自動裝配。是不是感覺@Autowired註解沒有任何限制?實際上會有兩種情況出現異常:
1、如果沒有匹配到Bean
可以使用@Autowired(required=false)即時沒有匹配到也不會異常,而是將值設置爲null。來看看@Autowired註解源碼:
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
/**
* Declares whether the annotated dependency is required.
* <p>Defaults to {@code true}.
*/
boolean required() default true;//required默認是true,必須滿足依賴否則異常,我們可以將這個值改爲fasle改變這一行爲
}
2、如果存在多個匹配的Bean
可以使用@Qualifier("users")來注入ID爲users的Bean。來看看@Qualifier註解源碼:
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Qualifier {
String value() default "";//默認是空字符串,也就是不指定匹配的Bean ID,必要時我們可以指定value的值(也就是Bean的ID)這時候會按照byName去自動裝配
}
下面來看下例子:
public class Roles {
private int id;
private String roleName;
@Autowired
private Users users;
//@Autowired(required=false)//即時沒匹配到ID爲users也不會異常,而是null
//@Qualifier("users")//獲得ID爲users的Bean
//private Users users;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
//沒有users的get,set方法
//重寫toString方法,方便測試
@Override
public String toString() {
return "Roles [id=" + id + ", roleName=" + roleName + ", users="
+ users + "]";
}
}
public class Users {
private int id;
private String name;
//省略set get方法
@Override
public String toString() {
return "Users [id=" + id + ", name=" + name + "]";
}
}
<bean id="roles" class="cn.com.ztz.spring.model.Roles">
<property name="id" value="1"/>
<property name="roleName" value="管理員"/>
</bean>
<bean id="users" class="cn.com.ztz.spring.model.Users">
<property name="id" value="2"/>
<property name="name" value="張三"/>
</bean>
<context:annotation-config/>
運行測試方法:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring.xml"})
public class JunitTest {
@Autowired
private Roles roles;
@Test
public void testSpring(){
System.out.println(roles);
}
}
Roles [id=1, roleName=管理員, users=Users [id=2, name=張三]]
@resource跟@Autowired的區別
@resource註解其實跟@Autowired差不多的,他們的區別是:
1、@resource是JDK的,@Autowired是Spring的
2、@resource按照byName自動裝配,@Autowired按照byType自動裝配。
@Autowired裝配順序
2、如果存在且唯一,則OK
3、如果不唯一,尋找name爲users的bean。因爲bean的name有唯一性,所以,到這裏應該能確定是否存在滿足要求的bean了
@Autowired也可以手動指定按照byName方式注入,使用@Qualifier標籤,例如:
@Autowired()
@Qualifier("users" )
@Resource裝配順序
1. 如果同時指定了name和type,則從Spring上下文中找到唯一匹配的bean進行裝配,找不到則拋出異常2. 如果指定了name,則從上下文中查找名稱(id)匹配的bean進行裝配,找不到則拋出異常
3. 如果指定了type,則從上下文中找到類型匹配的唯一bean進行裝配,找不到或者找到多個,都會拋出異常
4. 如果既沒有指定name,又沒有指定type,則自動按照byName方式進行裝配;如果沒有匹配,則回退爲一個原始類型進行匹配,如果匹配則自動裝配;
ps:有哪不對的地方,還請指出。