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);
	}
}

 

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