众所周知,Autowired注解是通过AutowiredAnnotationBeanPostProcessor来解析的
第一个问题
AutowiredAnnotationBeanPostProcessor在哪里注册的?
过程比较复杂,在使用xml和注解不同的场景中,略有不同,具体可以参考如下文章:
只是注册了,只是在beanDefinitionMap中有了org.springframework.context.annotation.internalAutowiredAnnotationProcessor元素而已,还没创建成AutowiredAnnotationBeanPostProcessor对象
此时的beanFactory的 singletonObjets中空空如也,也印证着确实没有AutowiredAnnotationBeanPostProcessor对象的存在
故而,引出第二个问题
经过debug得知,AutowiredAnnotationBeanPostProcessor是在registerBeanPostProcessors(beanFactory)这一步实例化的
看一下详细过程
- /**
- * Instantiate and register all BeanPostProcessor beans,
- * respecting explicit order if given.
- * <p>Must be called before any instantiation of application beans.
- */
- protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
- PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
- }
代码上的注释明白的写着,实例化和注册所有的BeanPostProcessor
进去 registerBeanPostProcessors后,一上来就是getBeanNamesForType,把类型是BeanPostProcessor.class的bean的名称都从容器获取出来
可以看到postProcessorNames有三个元素,internalAutowiredAnnotationProcessor赫然在列
拿到postProcessorNames后,循环遍历,进行getBean操作
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
里面有个小细节,getBean前还有一个if判断
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class))
判断这个BeanPostProcessor是否是PriorityOrdered类型
查看一下类图AutowiredAnnotationBeanPostProcessor,是实现了PriorityOrdered接口的
所以能顺理成章的进入getBean环节,后面的就是熟悉的流程了,getBean调用doGetBean,doGetBean会先调用getSingleton(beanName)在容器中找一下,找到就返回,这里肯定是没有的
没找到就继续调用createBean,doCreateBean,
然后调到createBeanInstance,instantiateBean
跟踪到最后,发现是用java的发射方式,生成了一个对象返回的
至此,AutowiredAnnotationBeanPostProcessor就被创建出来了
如果要简短一点概括,就是在执行refresh方法的registerBeanPostProcessors方法中,进行实例化的。
然后AutowiredAnnotationBeanPostProcessor的实例化就完成了,然后就引出了第三个问题,在哪调用的?
要深刻理解@Autowired,需要先掌握一个前置知识,就是spring对象的完整创建过程分为两步,实例化和初始化,这个和jvm的实例化初始化稍有不同,spring中的实例化只的是“半成品”对象,里面的属性还未完成赋值,而初始化就可以理解为完整的对象,里面的所有属性都完成了赋值。
多提一嘴,正是因为有了分两步创建对象的策略,循环依赖问题才可以得以解决,这是后话,改天单独分析。
严格的来说不是执行AutowiredAnnotationBeanPostProcessor,而是执行AutowiredAnnotationBeanPostProcessor类中的postProcessMergedBeanDefinition方法
这个过程发生在bean的创建过程中,当bean完成了实例化(还未完成初始化)时,会执行一个叫applyMergedBeanDefinitionPostProcessors的方法,对@Autowired进行预解析
预解析就是,识别被@Autowired标注了的属性、构造方法、方法等,并将上面的注解元数据信息缓存起来
我们可看到,这里循环调用的执行的是 MergedBeanDefinitionPostProcessor,咋一看这和我们的主角AutowiredAnnotationBeanPostProcessor毫无关系,怎么就会执行呢
这就要回到我们的 AutowiredAnnotationBeanPostProcessor类结构,可以看到不仅它实现了MergedBeanDefinitionPostProcessor接口,还实现了SmartInstantiationAwareBeanPostProcessor接口,所以这里是会执行的
写个小案例,Teacher中用@Autowired注入了Student
可以看到,在Teacher完成了实例化,并未完成初始化时,student的值还是null
值此“半成品”之际,applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)被执行,FactoryBean里面实现了MergedBeanDefinitionPostProcessor的BeanPostProcessor有多个,我们只关心AutowiredAnnotationBeanPostProcessor这个
findAutowiringMetadata,查找Autowired元数据
查找的细节就不深究了,总之,最终找到了student这个注解元数据,并且结果放到了injectionMetadataCache中。
值此,预解析完成。
在完成与解析之后,我们的Teacher对象还只是完成了实例化,还没有完成初始化,需要调用populateBean 进行属性的填充,@Autowired真正的解析就发生在这里
在populateBean中,主要是执行InstantiationAwareBeanPostProcessor的postProcessProperties方法进行属性的注入,和上面的一样,也是因为AutowiredAnnotationBeanPostProcessor间接的实现了InstantiationAwareBeanPostProcessor,所以才得以执行
我们进去看看postProcessProperties方法
先从预解析步骤已经解析了并缓存了的缓存中取出注解元数据
然后的核心就是
metadata.inject(bean, beanName, pvs);
从缓存中取出所有需要注入的 元素,这里只有一个student,调用element.inject
inject拿到student这个字段,检查是否已经处理过,没处理就要解析字段值
resolveFieldValue的过程非常复杂,复杂到我目前还没有整明白
总之,通过resolveFieldValue,返回了student的对象
然后通过反射方式field.set(bean, value)将student设置给Teacher对象,完成了我们的注入
后续继续执行initializeBean等方法,Teacher就算真正的完成创建了。
总结一下Spring中@Autowired注解装配的大体流程:
后续有空,在深入分析inject里面的逻辑,其中就包含经典面试题——autowired自动装配的两种方式:byName和byType的区别。