天天看点

Spring解决循环依赖问题

作者:奋斗的架构师

先看为什么循环依赖怎么出现的? 比如有AService和BService,具体代码如下:

class AService {
    @Autowired
    BService b;
}
class BService {
    @Autowired
    AService a;
}           

上面的代码 A中引入了B,B中引入了A,这样当spring实例A的时候,看到@Autowired引入了BService,然后会去实例化BService,实例化BService的时候,属性中又引入了AService,所以又会去实例化AService,如此循环下去产生了循环依赖。

解决方法

在实例化A后(属性注入之前),把它放入一个Map中暂时叫Map1,然后再注入属性,实例化B去,实例化B的时候,B又需要引入A,此时直接从前面的Map1中去取出,
此时取出的A和前面实例化的A是同一个引用。
然后B实例化完并且属性注入完成后,继续执行A的属性注入流程,后续A属性注入也完成了。因为A都是同一个引用,所以此时B中持有的是完整的A实例。
A实例化完整后,再把A放入另一个Map中,这个Map都是放完整的实例化后的类的,上面的Map1存放的是没有注入属性的实例化类。           

看样子不需要三级缓存了为什么还需要三级缓存?

三级缓存主要为了解决动态代理的问题。

下图总结的图片

Spring解决循环依赖问题

源码细节

protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
		...
		// 从三级缓存中获取实例对象的逻辑,注意这里可能来自于一级缓存/二级缓存/三级缓存
		Object sharedInstance = getSingleton(beanName);
		// 如果缓存中有,就进行一定的逻辑处理直接返回。
		if (sharedInstance != null && args == null) {
			// 返回实例对象。
			beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
		else {
	        // 调用创建实例的方法
			if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
					beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
		}
}

	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// Quick check for existing instance without full singleton lock
		// 从一级缓存读取实例对象(完整的实例对象)
		Object singletonObject = this.singletonObjects.get(beanName);
		// 如果一级缓存没有
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		    // 从二级缓存获取实例对象
			singletonObject = this.earlySingletonObjects.get(beanName);
			// 如果二级缓存没有
			if (singletonObject == null && allowEarlyReference) {
			    // 加一个锁,保证一致性,待研究
				synchronized (this.singletonObjects) {
					// Consistent creation of early reference within full singleton lock
					singletonObject = this.singletonObjects.get(beanName);
					// 一级缓存没有,从二级缓存拿
					if (singletonObject == null) {
						singletonObject = this.earlySingletonObjects.get(beanName);
						// 二级缓存没有,从三级缓存拿
						if (singletonObject == null) {
						    // 从三级缓存拿,拿出来的是一个FactoryBean
							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
							if (singletonFactory != null) {
							    // 调用FactoryBean的getObject方法。这里可能会生成代理对象,也可能是非代理对象
								singletonObject = singletonFactory.getObject();
								// 生成的对象,放入二级缓存
								this.earlySingletonObjects.put(beanName, singletonObject);
								// 删除三级缓存的类
								this.singletonFactories.remove(beanName);
							}
						}
					}
				}
			}
		}
		return singletonObject;
	}           

上面重要的方法是createBean,它调用了doCreateBean,它是重要的方法继续分析

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {
   // Eagerly cache singletons to be able to resolve circular references
   // even when triggered by lifecycle interfaces like BeanFactoryAware.
   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");
      }
      // 重要的方法,注意第二个参数是lamda表达式,看他传入的参数是ObjectFactory,只有一个方法getObject
           // 就是在上面getSingleton方法中会去调用触发的。addSingletonFactory会把ObjectFactory对象
           // 放入三级缓存中。
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
   }
   ...
   Object exposedObject = bean;
   try {
       // 属性注入,在这个方法中会再次执行doGetBean方法,第二次再此执行该方法的时候,缓存中就会存在第一次进入的时候实例化好的半成品bean了。
      populateBean(beanName, mbd, instanceWrapper);
      // 调用各种回调接口
      exposedObject = initializeBean(beanName, exposedObject, mbd);
   }
   }           

继续分析getEarlyBeanReference

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
      Object exposedObject = bean;
      if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            // 遍历实现了SmartInstantiationAwareBeanPostProcessor接口的实现类
         for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
                // 这里是获取FactoryBean实例的
            exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
         }
      }
      return exposedObject;
   }
/**
 * 此方法是核心,默认的实现是直接返回传入的bean实例
 */
default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
        return bean;
}           

这里还有一个SmartInstantiationAwareBeanPostProcessor的实现类,就是生产AOP代理类AbstractAutoProxyCreator,看它的getEarlyBeanReference方法

@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
      this.earlyProxyReferences.put(cacheKey, bean);
      return wrapIfNecessary(bean, beanName, cacheKey);
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        ...
        // Create proxy if we have advice.
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            // 生成动态代理,这块在我的另一个文档中分析动态代理生成的地方有提到。
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }
        ...
}