@Autowired和@Resource裝配

從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裝配順序

1、spring先找類型爲users的bean
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:有哪不對的地方,還請指出。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章