IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: 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来解析的

第一个问题

注册AutowiredAnnotationBeanPostProcessor

AutowiredAnnotationBeanPostProcessor在哪里注册的?

过程比较复杂,在使用xml和注解不同的场景中,略有不同,具体可以参考如下文章:

xml开发方式下AutowiredAnnotationBeanPostProcessor的注册时机https://blog.csdn.net/leisure_life/article/details/125570942?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22125570942%22%2C%22source%22%3A%22leisure_life%22%7D&ctrtid=u1pD4

注解开发方式下AutowiredAnnotationBeanPostProcessor的注册时机https://blog.csdn.net/leisure_life/article/details/125572151?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22125572151%22%2C%22source%22%3A%22leisure_life%22%7D&ctrtid=ifvaE

只是注册了,只是在beanDefinitionMap中有了org.springframework.context.annotation.internalAutowiredAnnotationProcessor元素而已,还没创建成AutowiredAnnotationBeanPostProcessor对象

?此时的beanFactory的 singletonObjets中空空如也,也印证着确实没有AutowiredAnnotationBeanPostProcessor对象的存在

故而,引出第二个问题

实例化AutowiredAnnotationBeanPostProcessor

经过debug得知,AutowiredAnnotationBeanPostProcessor是在registerBeanPostProcessors(beanFactory)这一步实例化的

?看一下详细过程

registerBeanPostProcessors

	/**
	 * 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,而是执行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方法

先从预解析步骤已经解析了并缓存了的缓存中取出注解元数据

?然后的核心就是

metadata.inject(bean, beanName, pvs);

从缓存中取出所有需要注入的 元素,这里只有一个student,调用element.inject

inject拿到student这个字段,检查是否已经处理过,没处理就要解析字段值

?resolveFieldValue的过程非常复杂,复杂到我目前还没有整明白

总之,通过resolveFieldValue,返回了student的对象

然后通过反射方式field.set(bean, value)将student设置给Teacher对象,完成了我们的注入

后续继续执行initializeBean等方法,Teacher就算真正的完成创建了。

总结

总结一下Spring中@Autowired注解装配的大体流程:

  1. 创建容器后都会通过AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)方法将一系列的internalXXXProcessor注册到容器,其中就包括internalAutowiredAnnotationProcessor
  2. 在执行registerBeanPostProcessors(beanFactory)时完成了AutowiredAnnotationBeanPostProcessor的创建与注册
  3. 在用户bean创建过程中(doCreateBean),实例化(createBeanInstance)之后,通过执行applyMergedBeanDefinitionPostProcessors方法,实现@Autowired注解元数据的预解析
  4. 在进行属性填充(populateBean)的过程中,通过调用InstantiationAwareBeanPostProcessor的postProcessProperties方法,在里面执行 inject 完成真正的注入

后续有空,在深入分析inject里面的逻辑,其中就包含经典面试题——autowired自动装配的两种方式:byName和byType的区别。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-07-05 23:25:28  更:2022-07-05 23:27:36 
 
开发: 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-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码