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