Spring容器初始化和解决循环依赖问题的分析

1. Spring IOC容器初始化过程:

Spring容器初始化和解决循环依赖问题的分析

2. bean的生命周期

Bean 容器找到配置文件中 Spring Bean 的定义。(beanDefintion)

Bean 容器利用 Java Reflection API 创建一个Bean的实例。(执行构造方法)

如果涉及到一些属性值 利用 set()方法设置一些属性值。(set属性)

如果 Bean 实现了 BeanNameAware 接口,调用 setBeanName()方法,传入Bean的名字。(aware接口的相关方法)

如果 Bean 实现了 BeanClassLoaderAware 接口,调用 setBeanClassLoader()方法,传入

ClassLoader对象的实例。

与上面的类似,如果实现了其他 *.Aware接口,就调用相应的方法。

如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor

对象,执行
postProcessBeforeInitialization() 方法 (BeanPostProcessor的before方法)

如果Bean实现了InitializingBean接口,执行afterPropertiesSet()方法。(afterPropertiesSet方法)

如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。(init-method方法)

如果有和加载这个 Bean的 Spring 容器相关的 BeanPostProcessor

对象,执行
postProcessAfterInitialization() 方法 (BeanPostProcessor的after方法(生成代理类))

当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接口,执行 destroy() 方法。(destroy方法)

当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。(destroy-method方法)

3. 什么是Spring的循环依赖?

一种是A依赖了B,B又依赖了A,

另一种情况是A自己依赖了自己。

无线套娃

4. Spring是如何解决循环依赖的?

Spring运用了三级缓存解决了循环依赖

singletonObjects:用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用

earlySingletonObjects:提前曝光的单例对象的cache,存放原始的 bean 对象(尚未填充属性),用于解决循环依赖

singletonFactories:单例对象工厂的cache,存放 bean 工厂对象,用于解决循环依赖

B中从三级缓存取出的A早期引用和A本身是一个引用,这样当A完成了初始化后,B中的A也完成了初始化

4.1 普通bean(未经代理的bean)解决循环依赖

如果单纯地解决普通bean循环依赖,A在赋值前,把早期bean放入缓存,然后B在赋值A时,从缓存中取出。其实用一层缓存就够了,为什么需要做3层缓存呢?

4.2 事务代理类解决循环依赖

上面说为什么需要做3层缓存,其中一个原因就是为了解决代理类的循环依赖。如果我们只用一层缓存,那么B依赖的就是一个普通的bean,而不是一个代理bean。

而我们的第三级缓存中调用的工厂方法

getEarlyBeanReference,会调用事务的后置处理器AbstractAutoProxyCreator的getEarlyBeanReference生成代理

AbstractAutoProxyCreator生成代理的方法做了处理,只会被代理一次,这样就解决了一个bean被多次代理(生成多个代理类)的问题

如果A被循环依赖且被事务代理,根据上面的逻辑,B中的A是代理类,而A自己因为循环依赖中的B先一步生成了A的代理,所以A不会在initializeBean中生成代理类。这样会导致两个bean不相等,所以spring在bean初始化的最后,会进行校验,如果A没有被代理并且缓存中有A,这样会把缓存中的A赋值A自己,这样就解决了两个A不一致的问题。

4.3 没有循环依赖的bean怎么生成代理类

没有循环依赖的话,initializeBean方法中会调用beanPostProcessor的after方法,生成所有的代理(包括事务)

4.4 其他的代理循环依赖报错

比如A加了@async,A->b->A就会循环依赖报错,

原因是bean在初始化最后校验中,如果发现A已经被代理,且被循环依赖,就会直接报错

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值