熟悉spring框架的同窗应该都知道spring单例使用的三级缓存,简单回顾下哪三级缓存,源码类:DefaultSingletonBeanRegistryjava
一级缓存,也就是直接将单例bean缓存至singletonObjects,去除其余缓存。设想下面这个场景web
没错,问题来了,循环依赖,死循环,直接凉凉。spring
对于直接使用一级缓存的问题已经暴露,如何解决?那么有同窗就要问了,那我在建立单例A时就直接将单例A放入缓存中不能够吗?这样不就解决了循环依赖问题?是的,这样处理是能够的。可是咱们如何判断从工厂中获取的一个单例初始化完成了?对单例的全部依赖注入的属性进行一次判空来判断?依赖注入的实例是否完成了初始化?使用工厂中的单例还要各类判空是否是很恶心?增长二级缓存岂不快哉
使用二级缓存:earlySingletonObjects+singletonObjectsexpress
能够看到咱们以前的问题所有迎刃而解,只要从工厂中的一级缓存中获取的单例均是完成了初始化,而且依赖注入的实例也均是完成了初始化,只是若是是循环依赖场景,可能获得的依赖注入时未完成初始化的,即某些依赖注入属性可能为null,例如:@Value注入的一些值。缓存
那么二级缓存已经解决了问题,为何还要引入三级缓存呢?设想下,若是我想要在读取二级缓存:earlySingletonObjects对象时统一增长一些日志或者其余处理动做,如何解决?在读取earlySingletonObjects对象实例后,对实例进行回调某些接口方法?固然没问题,能够看到spring对于非单例bean也采用该方法来处理前置、后置动做的回调。框架
else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } // getNonSingletonFactoryBeanForTypeCheck方法中也有一样对prototype类型bean的先后置回调处理代码
可是每次修改回调动做都要对全部读取earlySingletonObjects对象的地方进行修改,岂不是很恶心?每次增长一个读取earlySingletonObjects对象的动做都要记得加入相应的回调。是否是很容器遗漏和出错?那么若是咱们缓存的是一个接口而不是一个单例对象问题是否是就解决了呢?只须要对接口增长对应的动做便可,例如:svg
对于循环依赖注入的未完成初始化的单例,若是有特殊需求,指望保证其一些属性的提早注入,能够经过该扩展对提早曝光的对象进行一些个性化定制的处理,例如:将@Value的值提早从Environment中获取并注入到提早曝光的对象。而不须要修改框架代码,只须要增长对应的接口实现便可post
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'a': Unsatisfied dependency expressed through field 'b'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'b': Unsatisfied dependency expressed through field 'a'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'a': Requested bean is currently in creation: Is there an unresolvable circular reference?