spring中的循环依赖
循坏依赖指的是,A对象中持有B对象的引用,而B对象中持有A对象的引用,他们之间形成了循环依赖。或者是多个对象之间A依赖于B,B依赖于C,C又依赖A,形成循环依赖。又或者是对象自己依赖于自己。
在spring中实际上是使用三级缓存来解决循环依赖的,spring中的三级缓存分别是
/** 一级缓存,这里存放的对象是属性已经赋值完成的对象 */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** 二级缓存,用于存放实例化完成但是还未对属性赋值的对象 */
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
/** 三级缓存,存放生成单例bean的工厂 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
创建两个循环依赖的对象
@Component
public class A {
@Autowired
private B b;
}
@Component
public class B {
@Autowired
private A a;
}
spring中遇到循环依赖对象的创建步骤
1.在创建A对象时会先创建一个ObjectFactory工厂类
2.调用populateBean向A对象中注入属性
具体代码如下(AbstractAutowireCapableBeanFactory抽象类中的方法)
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
......
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//向第三级缓存中添加一个,ObjectFactory工厂类
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
Object exposedObject = bean;
try {
//向对象中注入属性
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
......
}
3.在注入属性时会在容器中寻找B对象但是没有找到B对象,则开始B对象的创建流程
4.在B对象的创建过程中同样会调用上面代码中的populateBean方法向B对象中A对象
5.这时候会调用getBean方法获取A对象
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
6.在获取A对象的时候会从缓存中尝试获取,这时候从三级缓存中可以获取到A对象的工厂
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object beanInstance;
// 这个方法里面就会创建A对象并且放入第二级缓存中
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
......
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
//获取到前面第一步中放入的ObjectFactory
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//创建A对象
singletonObject = singletonFactory.getObject();
//将A对象放入第二级缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
//将第三级缓存中的A对象的ObjectFactory移除
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
以上就是spring中解决循环依赖的方法