首先我们要了解spring 实例化bean的三步骤:
1) doCreateBeanInstance,通过无参构造方法创建一个bean的实例。
2) populateBean,填充bean的属性。
3) initialBean, 执行bean的初始化。
Spring的循环依赖主要发生在第一步和第二步。
Spring的依赖注入有三种情况:
1. 构造器注入,对于构造器注入形式的循环依赖, Spring框架无法自己解决。
2. 对于prototype 作用域类型的bean,形成的循环依赖,Spring框架也无法解决,因为Spring框架对prototype作用域的bean是不缓存的,无法提前暴露一个创建中的bean解决。
3. 对于setter形式的注入,形成的循环依赖,Spring框架是通过三级缓存解决的。
1) 一级缓存, singletonObjects。
2) 二级缓存, earlySingletonObjects。
3) 三级缓存,singletonFactories, 类型为ObjectFactory。
/** Cache of singleton objects: bean name --> bean instance */ private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); /** Cache of singleton factories: bean name --> ObjectFactory */ private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); /** Cache of early singleton objects: bean name --> bean instance */ private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
看一下getSingleton源码:
protected Object getSingleton(String beanName, boolean allowEarlyReference) { Object singletonObject = this.singletonObjects.get(beanName); //先直接从一级缓存里拿,如果拿到了就返回 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { // 二级缓存中取 singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { // 从三级缓存中取 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); // 从三级缓存中移到二级缓存 this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; }
通过ObjectFactory将被依赖的bean提前暴露出去,那么在用三级缓存的时候可以直接get出来。
标签:缓存,Spring,beanName,bean,依赖,singletonObject,循环 From: https://www.cnblogs.com/wyl010926/p/17744044.html