bean 生命周期

171 阅读3分钟
  1. BeanFactoryPostProcessor构造器

  2. BeanFactoryPostProcessor.postProcessBeanFactory

  3. BeanPostProcessor构造器

  4. BeanPostProcessor.postProcessBeforeInstantiation

  5. bean构造器

  6. BeanPostProcessor.postProcessPropertyValues

  7. bean字段设置

  8. BeanNameAware.setBeanName

  9. BeanFactoryAware.setBeanFactory

  10. BeanPostProcessor.postProcessBeforeInitialization

  11. InitializingBean.afterPropertiesSet

  12. bean.init-method

  13. BeanPostProcessor.postProcessAfterInitialization

面试官:”Spring是如何解决的循环依赖?

答:Spring通过三级缓存解决了循环依赖,其中一级缓存为单例池(singletonObjects),二级缓存为早期曝光对象earlySingletonObjects,三级缓存为早期曝光对象工厂(singletonFactories)。当A、B两个类发生循环引用时,在A完成实例化后,就使用实例化后的对象去创建一个对象工厂,并添加到三级缓存中,如果A被AOP代理,那么通过这个工厂获取到的就是A代理后的对象,如果A没有被AOP代理,那么这个工厂获取到的就是A实例化的对象。当A进行属性注入时,会去创建B,同时B又依赖了A,所以创建B的同时又会去调用getBean(a)来获取需要的依赖,此时的getBean(a)会从缓存中获取,第一步,先获取到三级缓存中的工厂;第二步,调用对象工工厂的getObject方法来获取到对应的对象,得到这个对象后将其注入到B中。紧接着B会走完它的生命周期流程,包括初始化、后置处理器等。当B创建完后,会将B再注入到A中,此时A再完成它的整个生命周期。至此,循环依赖结束!

面试官:”为什么要使用三级缓存呢?二级缓存能解决循环依赖吗?

答:如果要使用二级缓存解决循环依赖,意味着所有Bean在实例化后就要完成AOP代理,这样违背了Spring设计的原则,Spring在设计之初就是通过AnnotationAwareAspectJAutoProxyCreator这个后置处理器来在Bean生命周期的最后一步来完成AOP代理,而不是在实例化后就立马进行AOP代理。

bean的循环依赖解决,使用三级缓存,步骤:

依赖注入的时候,首先去一级缓存获取,这级缓存放的是完整的对象,如果没有 则先去二级缓存中获取对象,这级缓存放的是半成品对象(还未初始化),如果有,则注入,没有,则去三级缓存中去获取,这级缓存放的是生成该对象的工厂对象,如果没有,则触发依赖对象的创建,进入createBean阶段,如果有,则使用该工厂对象生成 对象,并将其放入二级缓存中,然后注入该对象。 createBean过程中,会生成该对象的工厂对象,并放入三级缓存中。

三级缓存的作用,防止发生循环依赖的时候,如果被依赖的对象需要生成代理对象(如果没有发生循环依赖,代理对象的生产是对象初始化完后才通过postProcessAfterInitialization生成的),会出现依赖的对象注入和被依赖对象生成的不一致的情况,发生循环依赖的时候,通过调用getEarlyBeanReference,提前生成代理对象,并且存到一个集合中,等后面对象初始化完后再走postProcessAfterInitialization时进行判断,就不需要再生成代理对象了。