spring解决循环依赖的3个map
时间: 2024-05-27 12:13:21 浏览: 154
可以使用三级缓存解决Spring中的循环依赖问题。这三个缓存分别是singletonObjects、earlySingletonObjects和singletonFactories。其中,singletonObjects缓存已经完全实例化完成的bean对象,earlySingletonObjects缓存已经被实例化但是存在循环依赖的bean对象,singletonFactories缓存已经被实例化但是存在循环依赖的InvocationHandler对象。这三个缓存的使用顺序如下:
1. 当Spring容器在创建bean的过程中,如果发现当前bean存在循环依赖,则会在singletonObjects缓存中查找是否已经创建完成,如果有则直接返回该对象。
2. 如果在singletonObjects缓存中没有找到,则继续在earlySingletonObjects缓存中查找是否已经存在创建过程中的bean(即从singletonFactories中创建的bean)。如果有,则将其返回。
3. 如果earlySingletonObjects缓存中也没有找到,那么就将当前bean对象放入earlySingletonObjects缓存中,继续创建该bean。
4. 当这个bean创建完成后,将其从earlySingletonObjects中移除并放入singletonObjects缓存中,同时根据bean定义中是否有AOP等特殊定义,将其放入相应的缓存中。
通过使用这种三级缓存的方式,Spring成功解决了循环依赖问题。
相关问题
解释一下spring如何解决循环依赖 并贴出相关源代码
Spring通过三级缓存解决循环依赖问题。当Spring创建一个Bean时,它会将该Bean放入第一级缓存中,然后检查该Bean所依赖的其他Bean是否已经创建,如果已经创建,则将这些Bean注入到该Bean中。如果其他Bean还没有创建,则将该Bean放入第二级缓存中,等待其他Bean创建完成后再进行注入。如果其他Bean也依赖于该Bean,则将该Bean放入第三级缓存中,等待其他Bean创建完成后再进行注入。
以下是相关的源代码:
```
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
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;
}
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
}
}
}
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
}
}
}
```
请注意,这只是Spring中解决循环依赖问题的一部分代码。完整的代码可以在Spring源代码中找到。
请解释一下spring中的三级缓存 三级缓存分别是什么?三个Map有什么异同? 什么是循环依赖?请你谈谈?看过spring源码吗? 如何检测是否存在循环依赖?实际开发中见过循环依赖的异常吗?
在Spring框架中,三级缓存是用于解决循环依赖问题的一种机制。三级缓存分别是singletonObjects、earlySingletonObjects和singletonFactories。
1. singletonObjects:该缓存用于存储完全初始化完成的单例对象。在对象创建完成后,会将其放入此缓存中。
2. earlySingletonObjects:该缓存用于存储早期曝光的未完全初始化的单例对象。在对象的创建过程中,如果发生循环依赖,会将正在创建的对象放入此缓存中。
3. singletonFactories:该缓存用于存储用于创建单例对象的工厂对象。当对象创建过程中发生循环依赖时,会将正在创建对象的工厂对象放入此缓存中。
这三个Map在Spring中的异同如下:
- 异同点:它们都是用于缓存单例对象的,用于解决循环依赖问题。
- 不同点:singletonObjects用于存储完全初始化完成的单例对象,而earlySingletonObjects和singletonFactories则分别用于存储未完全初始化的单例对象和创建单例对象的工厂对象。
循环依赖是指两个或多个Bean之间相互依赖形成了一个闭环,无法正确地创建这些Bean实例。例如,A依赖B,B又依赖A,就形成了循环依赖。在Spring中,循环依赖是一种容器级别的问题。
我了解Spring源码中的循环依赖处理机制,Spring通过使用三级缓存和提前曝光的方式来解决循环依赖问题。在对象创建过程中,当检测到循环依赖时,会从缓存中获取早期曝光的对象,从而避免了循环依赖带来的问题。
检测是否存在循环依赖可以通过构造器循环依赖来实现,当一个Bean在创建过程中多次被构造器引用,则说明存在循环依赖。Spring会抛出BeanCurrentlyInCreationException异常来表示循环依赖的存在。
在实际开发中,循环依赖是一个常见的问题。当Bean之间的依赖关系设计不当或者配置错误时,就可能出现循环依赖的异常。在这种情况下,我们需要仔细检查Bean的依赖关系,并进行适当的调整。
阅读全文