spring 如何解决循环依赖问题的?
作者:binspring使用了三级缓存去解决依赖问题的
我们在setter单例模式注入时,spring的bean加载过程是:
例如循环依赖关系:A->B->A
实现原理:
1.先加载A,依次判断(一级缓存)、(二级缓存)、(三级缓存)中是否有A,没有就将A加入(三级缓存)
2. A依赖B,先加载B
2.1 依次判断(一级缓存)、(二级缓存)、(三级缓存)中是否有B,没有就将B加入(三级缓存)
2.2 加载B的依赖,发现依赖A,依次从(一级缓存)、(二级缓存)、(三级缓存)中查找A,发现(三级缓存)有A,将A上升到(二级缓存)中
2.3 将A注入B的引用,完成B的加载,将B从(三级缓存)升级至(一级缓存)中
3.A依赖的B加载完了,继续加载A完成。将A从(二级缓存)上升到(一级缓存)。
关键源码:
在
AbstractAutowireCapableBeanFactorydo.CreateBean
中,就先将bean放入singletonFactories(三级缓存)
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { ..... //提前缓存单例,以便即使在诸如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"); } addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); }
核心判断代码
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { /**(一级缓存)已经完成加载的单例缓存. */ private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); /**(二级缓存)早期的单例对象缓存集合. */ private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); /**(三级缓存)单例的工厂Bean缓存集合. */ private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); ...... //以此从singletonObjects(一级缓存中)、earlySingletonObjects(二级缓存)、singletonFactories(三级缓存)中查找 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; }