一、@Autowired注解的用法
1.@Autowired注解应用于构造方法,示例如下:
public class Student { private String name; public Student() { } @Autowired public Student(String name) { this.name = name; } }
@Autowired加在构造方法上时,Spring会在推断构造方法阶段,选择该构造方法来进行实例化,在反射调用构造方法之前,会先根据构造方法参数类型、参数名从Spring容器中找到Bean对象,当做构造方法入参。
2.@Autowired注解应用于属性上,示例如下:
public class Student {
private String name;
@Autowired
private IBanjiMapper banji;
}
@Autowired加在某个属性上,Spring在进行Bean的生命周期过程中,在属性填充这一步,会基于实例化出来的对象,对该对象中加了@Autowired的属性自动给属性赋值。Spring会先根据属性的类型去Spring容器中找出该类型所有的Bean对象,如果找出来多个,则再根据属性的名字从多个中再确定一个,如果required属性为true,并且根据属性信息找不到对象,则直接抛异常。
3.@Autowired注解应用于方法上,示例如下:
@Autowired
public void setUserService(UserService userService){
this.userService = userService;
}
@Autowired注解写在某个方法上时,Spring在Bean生命周期的属性填充阶段,会根据方法的参数类型、参数名字从Spring容器找到对象当做方法入参,自动反射调用该方法。
二、@Autowired注解自动装配的过程
@Autowired:默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用(Spring提供)
@Qualifier():指定装配的bean,多个实例时可以结合@Autowired一起使用
@Primary:自动装配时当出现多个bean候选者时,被注解为@Primary
的bean将作为首选者
@Resource:默认按名称装配,当找不到与名称匹配的bean才会按类型装配
@Autowired通过Bean的后置处理器进行解析的
1.在创建一个Spring上下文的时候在构造函数中进行注册AutowiredAnnotationBeanPostProcessor
2.在Bean的创建过程中进行解析:
2.1预解析(解析@Autowired标注的属性、方法, 比如:把属性的类型、名称、属性所在的类...元数据缓存起来;
2.2在属性注入真正的解析(拿到上一步缓存的元数据去IOC容器进行查找,并且返回注入);
a.首先根据预解析的元数据拿到类型去容器中进行查找:
· 如果查询结果没有可以与之匹配的类,则会报异常 NoSuchBeanDefinitionException
· 如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据;
· 如果查询结果不止一个,那么@Autowired会根据名称来查找,如果还没有则会报错NoUniqueBeanDefinitionException
三、源码追踪
这里对@Autowired注解底层进行源码分析
@Autowired是用来装配bean的,肯定和bean的实例化有关,先经过了refresh方法,在finishBeanFactoryInitialization方法中getBean,然后走getObject的时候触发bean的初始化。bean的初始化是一个很复杂地方,在AbstractAutowireCapableBeanFactory#doCreateBean方法中,先创建一个BeanWrapper,它的内部成员变量wrappedObject中存放的就是实例化的MyService对象,[Spring Bean的生命周期源码详解 - 【Spring底层原理】,再往后进入populateBean方法进行属性注入
Spring对autowire注解的实现逻辑位于类:AutowiredAnnotationBeanPostProcessor#postProcessProperties之中,——>findAutowiringMetadata——>buildAutowiringMetadata,核心代码就在buildAutowiringMetadata方法里面
private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
} else {
List<InjectedElement> elements = new ArrayList();
// 需要处理的目标类
Class targetClass = clazz;
do {
List<InjectedElement> currElements = new ArrayList();
// 通过反射获取该类所有的字段,并遍历每一个字段,并通过方法
//findAutowiredAnnotation遍历每一个字段的所用注解,并如果用autowired修饰了,则返回
// auotowired相关属性
ReflectionUtils.doWithLocalFields(targetClass, (field) -> {
MergedAnnotation<?> ann = this.findAutowiredAnnotation(field);
if (ann != null) {
// 校验autowired注解是否用在了static方法上
if (Modifier.isStatic(field.getModifiers())) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
// 判断是否指定了required
boolean required = this.determineRequiredStatus(ann);
currElements.add(new AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement(field, required));
}
});