Spring自動裝配註解之@Autowired @Qualifier @Primary

目錄

1. 說明

2. 注入規則

3. 註解分析


1. 說明

Spring使用依賴注入,完成對IOC容器中各個組件的依賴注入,@Autowired就是Spring提供對其他組件注入的註解,@Autowired的定義如下:

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {

	/**
		定義組件的依賴是否是必輸的
	 */
	boolean required() default true;

}

2. 注入規則

1)、默認優先按照類型去容器中找對應的組件:applicationContext.getBean(UserDao.class),找到就賦值;
2)、如果找到多個相同類型的組件,再將屬性的名稱作爲組件的id去容器中查找 applicationContext.getBean("userDao")
3)、@Qualifier("userDao"):使用@Qualifier指定需要裝配的組件的id,而不是使用屬性名;
4)、自動裝配默認一定要將屬性賦值好,沒有就會報錯;可以使用@Autowired(required=false);
5)、@Primary:讓Spring進行自動裝配的時候,默認使用首選的bean,也可以繼續使用@Qualifier指定需要裝配的bean的名字;

3. 註解分析

調用鏈如下:

 

依賴注入攔截方法:org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor.postProcessPropertyValues(PropertyValues, PropertyDescriptor[], Object, String)

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement.inject(Object, String, PropertyValues)

@Override
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
	Field field = (Field) this.member;
	Object value;
	if (this.cached) {
		value = resolvedCachedArgument(beanName, this.cachedFieldValue);
	}
	else {
		DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
		desc.setContainingClass(bean.getClass());
		Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
		TypeConverter typeConverter = beanFactory.getTypeConverter();
		try {
			// 找出需要注入的組件
			value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
		}
		catch (BeansException ex) {
			throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
		}
		synchronized (this) {
			if (!this.cached) {
				if (value != null || this.required) {
					this.cachedFieldValue = desc;
					registerDependentBeans(beanName, autowiredBeanNames);
					if (autowiredBeanNames.size() == 1) {
						String autowiredBeanName = autowiredBeanNames.iterator().next();
						if (beanFactory.containsBean(autowiredBeanName)) {
							if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
								this.cachedFieldValue = new ShortcutDependencyDescriptor(
										desc, autowiredBeanName, field.getType());
							}
						}
					}
				}
				else {
					this.cachedFieldValue = null;
				}
				this.cached = true;
			}
		}
	}
	if (value != null) {
		ReflectionUtils.makeAccessible(field);
		//依賴注入
		field.set(bean, value);
	}
}

 

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