spring中bean如何实现初始化以及循环引用
创始人
2024-11-16 04:42:44
0次

1、点进这个方法里面。

spring中bean如何实现初始化以及循环引用

这个方法是反射调用类中的 factoryMethod 方法。 这要知道@Bean 方法的原理, 实际上spring 会扫描有@bean 注解的方法, 然后把方法名称设置到 BeanDefinition 的 factoryMethod属性中, 接下来就会调到上面截图中的方法实现@Bean 方法的调用。

2、 有参构造函数的时候

spring中bean如何实现初始化以及循环引用

determineConstructorsFromBeanPostProcessors这个方法是 BeanPostProcessor 接口类的首次应用, 最终会掉到
AutowiredAnnotationBeanPostProcessor 类的方法, 在方法中会扫描有注解的构造函数然后完成装配过程。 然后把有有@Autowired 注解的构造函数返回。

3、 无参构造函数的实例化

spring中bean如何实现初始化以及循环引用

这就是简单的反射实例化。 大部分类的实例化都会走这个逻辑

4、 类中注解的收集

实例化完成后接下来就需要对类中的属性进行依赖注入操作, 但是类里面属性和方法的依赖注入往往用@Autowired 或者@Resource 注解, 那么这些注解的依赖注入是如何完成的呢?

注解的收集:

spring中bean如何实现初始化以及循环引用

也是通过 BeanPostProcessor 接口类型实例来挨个处理的。

A、 首先是CommonAnnotationBeanPostProcessor 类, 这个类完成了@Resource 注解的属性或者方法的收集

这个类还对@PostConstruct 和@PreDestory 支持

spring中bean如何实现初始化以及循环引用

收集过程

1、 看缓存里面有没有 InjectionMetadata 对象

2、 从类中获取所有 Field 对象, 循环 field 对象, 判断 field 有没有@Resource 注解,如果有注解封装成 ResourceElement 对象

3、 从类中获取所有 Method 对象, 循环 Method 对象, 判断 Method 有没有@Resource

注解, 如果有注解封装成 ResourceElement 对象

4、 最终把两个 field 和 Method 封装的对象集合封装到 InjectionMetadata 对象中

B、 然后是AutowiredAnnotationBeanPostProcessor 类, 对@Autowired 注解的属性和方法的收集。 收集过程基本上跟@Resource 注解的收集差不多, 这里就不赘述了

5、 IOC\DI 依

对应的方法:

spring中bean如何实现初始化以及循环引用

spring中bean如何实现初始化以及循环引用

这里又是一个 BeanPostProcessor 类型接口的运用, 前面我们讲到了@Resource@Autowired 注解的收集, 那么这个方法就是根据收集到的注解进行反射调用。

循环收集到的 metaData 中的 list 对象, 然后挨个调用里面的 InjectedElement 的inject 方法完成依赖注入。

spring中bean如何实现初始化以及循环引用

其中 value 值的获取, 如果依赖的属性是一个引用类型必定会触发该属性的BeanFactory.getBean 操作, 从而从 spring 容器中获取到对应的实例。 方法的依赖注入类似这里就不再赘述。

6、 bean 实例化后的操作

代码走到这里:

spring中bean如何实现初始化以及循环引用

A、 首先是对某些 Aware 接口的调用

spring中bean如何实现初始化以及循环引用

B、 然后@PostConstruct 注解方法的调用

spring中bean如何实现初始化以及循环引用

这里又是一个 BeanPostProcessor 接口的运用,前面讲过, 有@PostConstruct 注解的方法会收集到一个 met就是通过 BeanPostProcessor 接口调到CommonAnnotationBeanPostProcessor 类, 然后在类中拿根据对象里面的容器来反射调用有注解的方法。 代码如下:

spring中bean如何实现初始化以及循环引用

spring中bean如何实现初始化以及循环引用

有@PostConstruct 注解的容器会收集到 initMethods 容器中, 接下来就是方法的

反射调用。

spring中bean如何实现初始化以及循环引用

C、 InitializingBean 接口和 init-method 属性调用

spring中bean如何实现初始化以及循环引用

Init-method 属性调用是在 afterPropertiesSet 之后

spring中bean如何实现初始化以及循环引用

afterPropertiesSet和Init-method和有@PostConstruct注解的方法其实核心功能都是一样的, 只是调用时序不一样而已, 都是在该类实例化和 IOC 做完后调用的, 我们可以在这些方法中做一些在 spring 或者 servlet 容器启动的时候的初始化工作。 比如缓存预热, 比如缓存数据加载到内存, 比如配置解析, 等等初始化工作。

在这个方法里面还有一个重要的逻辑

spring中bean如何实现初始化以及循环引用

也是一个 BeanPostProcessor 接口的运用, 在这里会返回 bean 的代理实例, 这个就是 AOP 的入口。

D、 FactoryBean 接口

带入如下:

spring中bean如何实现初始化以及循环引用

在实例化和 IOC/DI 做完后, 就会调用 FactoryBean 类型的接口, 如果要获取到FactoryBean 类本身, 就必须加上”&”符号, 比如beanFactory.getBean(“&beanName” )。


spring中bean如何实现初始化以及循环引用

BeanFactory.getBean(“beanName”)只能获取到getObject()方法返回的实例。

getObject方法返回的实例会有单独的缓存存储, 跟其他实例不是同一个缓存, 对应的缓存是:factoryBeanObjectCache

E、 循环依赖

循环依赖请参照流程图理解https://www.processon.com/view/link/5df9ce52e4b0c4255ea1a84f

循环依赖只会出现在单例实例无参构造函数实例化情况下

有参构造函数的加@Autowired 的方式循环依赖是直接报错的, 多例的循环依赖也是直接报错的

spring中bean如何实现初始化以及循环引用

spring中bean如何实现初始化以及循环引用

循环依赖步骤:

1、 A 类无参构造函数实例化后, 设置三级缓存

2、 A 类 populateBean 进行依赖注入, 这里触发了 B 类属性的 getBean 操作

3、 B 类无参构造函数实例化后, 设置三级缓存

4、 B 类 populateBean 进行依赖注入, 这里触发了 A 类属性的 getBean 操作

5、 A 类之前正在实例化, singletonsCurrentlyInCreation 集合中有已经有这个 A 类了, 三级缓存里面也有了, 所以这时候是从三级缓存中拿到的提前暴露的A 实例, 该实例还没有进行 B 类属性的依赖注入的, B 类属性为空。

6、 B 类拿到了 A 的提前暴露实例注入到 A 类属性中了

7、 B 类实例化已经完成, B 类的实例化是由 A 类实例化中 B 属性的依赖注入触发的 getBean 操作进行的, 现在 B 已经实例化, 所以 A 类中 B 属性就可以完成依赖注入了, 这时候 A 类 B 属性已经有值了

8、 B 类 A 属性指向的就是 A 类实例堆空间, 所以这时候 B 类 A 属性也会有值了。

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...