| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Java知识库 -> Spring中@Autowired注解装配流程 -> 正文阅读 |
|
[Java知识库]Spring中@Autowired注解装配流程 |
众所周知,Autowired注解是通过AutowiredAnnotationBeanPostProcessor来解析的 第一个问题 注册AutowiredAnnotationBeanPostProcessorAutowiredAnnotationBeanPostProcessor在哪里注册的? 过程比较复杂,在使用xml和注解不同的场景中,略有不同,具体可以参考如下文章: 只是注册了,只是在beanDefinitionMap中有了org.springframework.context.annotation.internalAutowiredAnnotationProcessor元素而已,还没创建成AutowiredAnnotationBeanPostProcessor对象 ?此时的beanFactory的 singletonObjets中空空如也,也印证着确实没有AutowiredAnnotationBeanPostProcessor对象的存在 故而,引出第二个问题 实例化AutowiredAnnotationBeanPostProcessor经过debug得知,AutowiredAnnotationBeanPostProcessor是在registerBeanPostProcessors(beanFactory)这一步实例化的 ?看一下详细过程 registerBeanPostProcessors
代码上的注释明白的写着,实例化和注册所有的BeanPostProcessor 进去?registerBeanPostProcessors后,一上来就是getBeanNamesForType,把类型是BeanPostProcessor.class的bean的名称都从容器获取出来 可以看到postProcessorNames有三个元素,internalAutowiredAnnotationProcessor赫然在列 ?拿到postProcessorNames后,循环遍历,进行getBean操作
里面有个小细节,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,而是执行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在populateBean中,主要是执行InstantiationAwareBeanPostProcessor的postProcessProperties方法进行属性的注入,和上面的一样,也是因为AutowiredAnnotationBeanPostProcessor间接的实现了InstantiationAwareBeanPostProcessor,所以才得以执行 ?我们进去看看postProcessProperties方法 先从预解析步骤已经解析了并缓存了的缓存中取出注解元数据 ?然后的核心就是
从缓存中取出所有需要注入的 元素,这里只有一个student,调用element.inject inject拿到student这个字段,检查是否已经处理过,没处理就要解析字段值 ?resolveFieldValue的过程非常复杂,复杂到我目前还没有整明白 总之,通过resolveFieldValue,返回了student的对象 然后通过反射方式field.set(bean, value)将student设置给Teacher对象,完成了我们的注入 后续继续执行initializeBean等方法,Teacher就算真正的完成创建了。 总结总结一下Spring中@Autowired注解装配的大体流程:
后续有空,在深入分析inject里面的逻辑,其中就包含经典面试题——autowired自动装配的两种方式:byName和byType的区别。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 15:20:53- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |