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.

 

posted @ 2020-03-21 20:06  abcwt112  阅读(1806)  评论(0编辑  收藏  举报