Spring @Autowired 原理
主题
学习分享记录一下Spring是怎么注入@Autowired标注的bean的.
配置BeanPostProcessor
传统的spring项目中配置基本是通过XML来操作的.在XML中经常会有这种配置
<context:annotation-config/> 或者 <context:component-scan>
或者类似的配置.这些配置是开启@Autowired等注解的关键. 先看看他们做了什么.
解析标签
XML中这些特殊的namespace基本都是由XXXNameSpaceHandler来做解析的
比如AOPNamspaceHandler负责解析 <aop:aspectj-autoproxy /> 等命名空间
类似的context:XXX这种命名空间基本是由ContextNamespaceHandler来做处理.
他会解析一大堆标签,其中我们主要要研究的额就是component-scan和annotation-config...功能有一部分重叠.
ComponentScanBeanDefinitionParser的parse方法会调用org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object) 这个方法
看方法内部不难看出它往registry(BeanFactory)中添加了很多特殊的BeanPostProcessor (或者其子类).我们比较关心的是AutowiredAnnotationBeanPostProcessor
BeanPostProcessor
BPP这些特殊的bean会参与Spring的生命周期.
这个类最重要的地方在于impl了InstantiationAwareBeanPostProcessor和MergedBeanDefinitionPostProcessor了.
其中有3个方法的覆盖比较关键.
第一个是MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition
这个时间点大致是在BeanFactory准备根据beanDifinition去创建bean的时候.会回调这个方法.
AutowiredAnnotationBeanPostProcessor在这一步骤中取查找bean有标记了@Autowired的field,method等InjectionMetadata.InjectedElement的实现..
具体的业务逻辑就不想详细说明了.基本就是通过反射去查找要注入的元素,然后封装到元信息里保存下来.
第二个是InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation返回为true.(常规的bean都会返回true)
InstantiationAwareBeanPostProcessor可以通过这个false参数来阻止属性的注入.
当然正常情况下这里一般方式(比如XML中注入属性)也是允许的,所以这里返回true.这就意味着bean定义和bean的部分属性可以定义在XML中走一般的属性注入.
而这个bean的部分属性加上@Autowired,通过注解注入也是可以的..只是可能很少会有人这么做.
当然,设置为false的话@Autowired也不能注入.因为有短路原则.满足这种情况的话只有BeanPostProcessor.postProcessAfterInitialization会被调用.
第三个方法是InstantiationAwareBeanPostProcessor.postProcessPropertyValues
这个回调函数发生的时间是在BeanFactory去populateBean的时候.也就是说bean已经new了.正在初始化他的属性,且通过正常方式(比如XML里定义的属性)已经完成的时候.
通过获取之前第一步中记录下来的metaData.InjectedElement.对于每一个element去掉inject方法.
method和field因为是2种实现类.所以方法实现会有一点点区别.但是大致还是一样的...可以来看看field的.
最核心的也就是.问BF去取bean.
我有一个field.我有一个需要的type.你BF找到bean给我..就这样.
https://www.cnblogs.com/binarylei/p/12337145.html
可以参考上面这篇文章怎么从BF中取bean.
绝大部分情况下基本就是从BeanDifination中取出类型匹配的bean的name.然后再去找对应的bean.
找到了bean以后就通过field.set去设置一下即可.
小结
1.Spring中这么多骚操作离不开BeanPostProcessor等特殊的bean.在XML对应的applicationContext的时候通过NamspaceHandler解析XML节点,并去注册AutowiredAnnotationBeanPostProcessor等bean.
2.AutowiredAnnotationBeanPostProcessor
通过MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition在doCreateBean当前bean的时候收集当前的需要@Auwotired的element的元数据信息
通过InstantiationAwareBeanPostProcessor.postProcessPropertyValues在populateBean的时候,即设置当前bean的属性的时候获取之前的需要注入的elment.然后去BF中获取对应的bean.并set.