熟悉spring框架的同学应该都知道spring单例使用的三级缓存,简单回顾下哪三级缓存,源码类:DefaultSingletonBeanRegistry
一级缓存,也就是直接将单例bean缓存至singletonObjects,去除其他缓存。设想下面这个场景
没错,问题来了,循环依赖,死循环,直接凉凉。
对于直接使用一级缓存的问题已经暴露,如何解决?那么有同学就要问了,那我在创建单例A时就直接将单例A放入缓存中不可以吗?这样不就解决了循环依赖问题?是的,这样处理是可以的。但是我们如何判断从工厂中获取的一个单例初始化完成了?对单例的所有依赖注入的属性进行一次判空来判断?依赖注入的实例是否完成了初始化?使用工厂中的单例还要各种判空是不是很恶心?增加二级缓存岂不快哉
使用二级缓存:earlySingletonObjects+singletonObjects
可以看到我们之前的问题全部迎刃而解,只要从工厂中的一级缓存中获取的单例均是完成了初始化,并且依赖注入的实例也均是完成了初始化,只是如果是循环依赖场景,可能得到的依赖注入时未完成初始化的,即某些依赖注入属性可能为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对象的动作都要记得加入相应的回调。是不是很容器遗漏和出错?那么如果我们缓存的是一个接口而不是一个单例对象问题是不是就解决了呢?只需要对接口增加对应的动作即可,例如:
对于循环依赖注入的未完成初始化的单例,如果有特殊需求,期望保证其一些属性的提前注入,可以通过该扩展对提前曝光的对象进行一些个性化定制的处理,例如:将@Value的值提前从Environment中获取并注入到提前曝光的对象。而不需要修改框架代码,只需要增加对应的接口实现即可
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?
本文地址:https://blog.csdn.net/u010597819/article/details/107595103
如对本文有疑问, 点击进行留言回复!!
before社区电量是什么意思 Before社区电量获得方法
RecycleView入门详解(教你全面掌握RecycleView用法)
动态权限请求框架RxPermissions(几行代码搞定权限)
URL路径@PathVariable出现点号“.“时值遭截断问题
网友评论