spring循环依赖及解决方案

1.Spring中的缓存

1.1.一级缓存

作用:

限制Bean在beanFactory中只有一份,即实现singleton scope;

如图:
在这里插入图片描述
说明:

①.首次通过getBean()方法获取对象A的实例,缓存中还没有对象A的实例,接着就会创建对象的实例;

②.将对象A的实例放入缓存中,等到下一次获取该对象实例的时候直接从缓存中获取;

循环依赖:
在这里插入图片描述
说明:

①.首次通过getBean()方法获取对象A的实例,缓存中还没有对象A的实例,接着就会创建对象A的实例;

②.执行对象A中的setB(?)方法,注入对象B,该过程会间接调用到对象B中的getBean()方法;

③.对象B中的getBean()方法在首次执行的时候,由于缓存中并没有对象B的实例,因此也会创建对象B的实例;

④.对象B的实例被创建之后,会通过setA(?)方法注入对象A,此时又会间接调用对象A中的getBean()方法,由于之前对象A创建的实例还没有存入到一级缓存中,此时又会创建对象A的实例,将上面的步骤又会被执行…

⑤.如此反反复复,就会出现死循环!

结论:

一级缓存并不能解决循环依赖!

1.2.二级缓存(Spring中它叫三级缓存)

作用:

解决循环依赖;

如图:
在这里插入图片描述
说明:

①.首次通过getBean()方法获取对象A的实例.一级缓存中(即singletonObjects)还没有对象A的实例,接着就会创建对象A的实例;

②.对象A的实例创建之后,将它存放到二级缓存中(即singletonFactories,此时缓存中的对象A的实例只是一个半成品);

③.执行对象A中的setB(?)方法注入对象B,首先从二级缓存中取对象B的实例(半成品),发现没有,然后就间接调用对象B的getBean()方法;

④.执行对象B的getBean()方法,首先也要从一级缓存中取对象B的实例,没有找到,就创建对象B的实例,创建之后也会将它放入二级缓存中(此时缓存中的对象B的实例也是一个半成品);

⑤.接着对象B通过setA(?)方法注入对象A,首先从二级缓存中取对象A的实例(半成品),现在可以从二级缓存中取到对象A的实例(半成品),完成依赖注入;

⑥.对象B继续执行.完成初始化,再将一个完整的对象B的实例放入到一级缓存中,而二级缓存中的临时的对象B的实例(半成品)就会被清除;

⑦.回到对象A的getBean()方法中,对象A在setB(?)方法注入对象B的过程中会得到一个完整的对象B的实例,借此完成对象B的注入;

⑧.然后对象A继续执行,完成初始化,再将一个完整的对象A的实例放入到一级缓存中,而是二级缓存中的临时的对象A的实例(半成品)也会被清除;

⑨.到此,借助二级缓存就完成了对象的依赖注入;

⑩.当依赖注入完成之后,一级缓存中就存在对象A,对象B的对应的实例了,之后要使用对象A,对象B的实例时就可以直接从一级缓存中获取了;

循环依赖中存在代理的情况:
在这里插入图片描述
说明:

①.首次通过getBean()方法获取对象A的实例.一级缓存中(即singletonObjects)还没有对象A的实例,接着就会创建对象A的实例;

②.对象A的实例创建之后,将它存放到二级缓存中(即singletonFactories,此时缓存中的对象A的实例只是一个半成品);

③.执行对象A中的setB(?)方法注入对象B,首先从二级缓存中取对象B的实例(半成品),发现没有,然后就间接调用对象B的getBean()方法;

④.执行对象B的getBean()方法,首先也要从一级缓存中取对象B的实例,没有找到,就创建对象B的实例,创建之后也会将它放入二级缓存中(此时缓存中的对象B的实例也是一个半成品);

⑤.接着对象B通过setA(?)方法注入对象A,首先从二级缓存中取对象A的实例(半成品),现在可以从二级缓存中取到对象A的实例(半成品),完成依赖注入;

⑥.对象B继续执行.完成初始化,紧接着生成代理对象(可能是需要对对象B的功能进行增强);

⑦.再将一个完整的对象B的代理对象放入到一级缓存中,而二级缓存中的临时的对象B的实例(半成品)就会被清除;

⑧.回到对象A的getBean()方法中,对象A在setB(?)方法注入对象B的过程中会得到一个完整的对象B的代理对象,借此完成依赖注入;

⑨.然后对象A继续执行,完成初始化,生成代理对象,再将一个完整的对象A的代理对象放入到一级缓存中,而是二级缓存中的临时的对象A的实例(半成品)也会被清除;

问题:

上面第⑤步,对象B通过setA(?)方法注入对象A的时候,从二级缓存中拿到的并不是代理对象,这样就会造成后续调用对象B的相关功能而用到了对象A相关功能的时候,对象A的相关功能并没有如期增强!

结论:

二级缓存可以解决正常情况下的循环依赖,但是不能解决循环依赖中存在代理的情况!

1.3.三级缓存(Spring中它叫二级缓存)

作用:

解决循环依赖中代理创建过晚的问题;

如图:
在这里插入图片描述
说明:

①.首次通过getBean()方法获取对象A的实例.一级缓存中(即singletonObjects)还没有对象A的实例,接着就会创建对象A的实例;

②.对象A的实例创建之后,将一个工厂对象fa存放到二级缓存中(即singletonFactories,工厂对象之后会生成一个代理对象或者实例对象(半成品));

③.执行对象A中的setB(?)方法注入对象B,首先从二级缓存中取对象B的实例(半成品),发现没有,然后就间接调用对象B的getBean()方法;

④.执行对象B的getBean()方法,首先也要从一级缓存中取对象B的实例,没有找到,就创建对象B的实例,创建之后也会将一个工厂对象fb存放到二级缓存中(工厂对象之后会生成一个代理对象或者实例对象(半成品));

⑤.接着对象B通过setA(?)方法注入对象A,首先从二级缓存中取对象A的实例(半成品),此时找到的是一个工厂对象fa,工厂对象fa会判断是否发生了循环依赖,如果发生了循环依赖,生成一个完整的对象A的代理对象返回,同时将代理对象pa存放到三级缓存中(即earlySingletonObjects)以及清除二级缓存中的工厂对象fa;如果没有发生循环依赖,则返回对象A的实例(半成品).由于当前发生了循环依赖,那么从二级缓存中取到的就是一个完整的对象A的代理对象pa,借助这个代理对象完成依赖注入;

⑥.对象B继续执行.完成初始化,之后再从三级缓存中取代理对象,如果没有就创建代理对象,如果有直接使用,之后再将代理对象pb放入到一级缓存中,之后清除二级和三级缓存中对象B的临时对象(pb,fb…);

⑦.回到对象A的getBean()方法中,对象A在setB(?)方法注入对象B的过程中会得到一个完整的对象B的代理对象pb,借此完成依赖注入;

⑨.然后对象A继续执行,完成初始化,再从三级缓存中取代理对象,如果没有就创建代理对象,如果有直接使用,再将代理对象pa放入到一级缓存中,然后清除三级缓存中对象A的临时对象(pa…);

⑩.当依赖注入完成之后,一级缓存中就存在对象A,对象B的对应的代理对象了,之后要使用对象A,对象B的实例时就可以直接从一级缓存中取到对应对象的代理对象;

结论:

三级缓存可以解决循环依赖问题!

2.Spring中的循环依赖

1>.循环依赖就循环引用,就是两个或多个bean相互之间持有对方,比如A对象引用了B对象,B对象引用了C对象,C对象引用了A对象,最终形成一个闭环.此处不是循环调用,循环调用是方法之间的循环调用,如图所示:
在这里插入图片描述
2>.循环调用是无法解决的,除非有终结条件,否则就是死循环,最终导致内存溢出错误;

Spring如何解决循环依赖?

Spring容器循环依赖包括构造器循环依赖和setter循环依赖.那么Spring容器如何解决循环依赖呢?

2.1.setter循环依赖

1>.表示通过setter注入方式构成的循环依赖;

2>.示例代码如下:

public class A{
    private B b;
    public void setB(B b){
        this.b=b;
    }
    //...
}

public class B{
    private A a;
    public void setA(A a){
        this.a=a;
    }
    //...
}

3>.解决方案:使用三级缓存来解决setter循环依赖问题

AbstracBeanFactory#doGetBean

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
   String beanName = this.transformedBeanName(name);
   //从缓存获取对象
   Object sharedInstance = this.getSingleton(beanName);
   Object beanInstance;
   if (sharedInstance != null && args == null) {
       if (this.logger.isTraceEnabled()) {
           if (this.isSingletonCurrentlyInCreation(beanName)) {
               this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
           } else {
               this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
           }
       }

       beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
   } else {
       if (this.isPrototypeCurrentlyInCreation(beanName)) {
           throw new BeanCurrentlyInCreationException(beanName);
       }

       BeanFactory parentBeanFactory = this.getParentBeanFactory();
       if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
           String nameToLookup = this.originalBeanName(name);
           if (parentBeanFactory instanceof AbstractBeanFactory) {
               return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
           }

           if (args != null) {
               return parentBeanFactory.getBean(nameToLookup, args);
           }

           if (requiredType != null) {
               return parentBeanFactory.getBean(nameToLookup, requiredType);
           }

           return parentBeanFactory.getBean(nameToLookup);
       }

       if (!typeCheckOnly) {
           this.markBeanAsCreated(beanName);
       }

       StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);

       try {
           if (requiredType != null) {
               beanCreation.tag("beanType", requiredType::toString);
           }

           RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
           this.checkMergedBeanDefinition(mbd, beanName, args);
           String[] dependsOn = mbd.getDependsOn();
           String[] var12;
           if (dependsOn != null) {
               var12 = dependsOn;
               int var13 = dependsOn.length;

               for(int var14 = 0; var14 < var13; ++var14) {
                   String dep = var12[var14];
                   if (this.isDependent(beanName, dep)) {
                       throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                   }

                   this.registerDependentBean(dep, beanName);

                   try {
                       this.getBean(dep);
                   } catch (NoSuchBeanDefinitionException var31) {
                       throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var31);
                   }
               }
           }

           if (mbd.isSingleton()) {
               sharedInstance = this.getSingleton(beanName, () -> {
                   try {
                       //创建对象
                       return this.createBean(beanName, mbd, args);
                   } catch (BeansException var5) {
                       this.destroySingleton(beanName);
                       throw var5;
                   }
               });
               beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
           } else if (mbd.isPrototype()) {
               var12 = null;

               Object prototypeInstance;
               try {
                   this.beforePrototypeCreation(beanName);
                   prototypeInstance = this.createBean(beanName, mbd, args);
               } finally {
                   this.afterPrototypeCreation(beanName);
               }

               beanInstance = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
           } else {
               String scopeName = mbd.getScope();
               if (!StringUtils.hasLength(scopeName)) {
                   throw new IllegalStateException("No scope name defined for bean ��" + beanName + "'");
               }

               Scope scope = (Scope)this.scopes.get(scopeName);
               if (scope == null) {
                   throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
               }

               try {
                   Object scopedInstance = scope.get(beanName, () -> {
                       this.beforePrototypeCreation(beanName);

                       Object var4;
                       try {
                           var4 = this.createBean(beanName, mbd, args);
                       } finally {
                           this.afterPrototypeCreation(beanName);
                       }

                       return var4;
                   });
                   beanInstance = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
               } catch (IllegalStateException var30) {
                   throw new ScopeNotActiveException(beanName, scopeName, var30);
               }
           }
       } catch (BeansException var32) {
           beanCreation.tag("exception", var32.getClass().toString());
           beanCreation.tag("message", String.valueOf(var32.getMessage()));
           this.cleanupAfterBeanCreationFailure(beanName);
           throw var32;
       } finally {
           beanCreation.end();
       }
   }

   return this.adaptBeanInstance(name, beanInstance, requiredType);
}

DefaultSingletonBeanRegistry#getSingleton

@Nullable
   protected Object getSingleton(String beanName, boolean allowEarlyReference) {
       //从一级缓存中取对象
       Object singletonObject = this.singletonObjects.get(beanName);
       if (singletonObject == null && this.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<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                           if (singletonFactory != null) {
                               singletonObject = singletonFactory.getObject();
                               //将对象放入到二级缓存中
                               this.earlySingletonObjects.put(beanName, singletonObject);
                               //清除三级缓存中的临时对象(工厂对象)
                               this.singletonFactories.remove(beanName);
                           }
                       }
                   }
               }
           }
       }

       return singletonObject;
   }

AbstractAutowireCapableBeanFactory#doCreateBean

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
      BeanWrapper instanceWrapper = null;
       if (mbd.isSingleton()) {
           instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
       }

       if (instanceWrapper == null) {
           instanceWrapper = this.createBeanInstance(beanName, mbd, args);
       }

       Object bean = instanceWrapper.getWrappedInstance();
       Class<?> beanType = instanceWrapper.getWrappedClass();
       if (beanType != NullBean.class) {
           mbd.resolvedTargetType = beanType;
       }

       synchronized(mbd.postProcessingLock) {
           if (!mbd.postProcessed) {
               try {
                   this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
               } catch (Throwable var17) {
                   throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
               }

               mbd.postProcessed = true;
           }
       }

       boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
       if (earlySingletonExposure) {
           if (this.logger.isTraceEnabled()) {
               this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
           }

           //将对象工厂存放到三级缓存
           this.addSingletonFactory(beanName, () -> {
               return this.getEarlyBeanReference(beanName, mbd, bean);
           });
       }

       //bean为原始对象
       Object exposedObject = bean;

       try {
           //依赖注入
           this.populateBean(beanName, mbd, instanceWrapper);
           //Bean初始化,有可能会创建代理对象
           exposedObject = this.initializeBean(beanName, exposedObject, mbd);
       } catch (Throwable var18) {
           if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
               throw (BeanCreationException)var18;
           }

           throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
       }
       if (earlySingletonExposure) {
           Object earlySingletonReference = this.getSingleton(beanName, false);
           if (earlySingletonReference != null) {
               //判断原始对象和初始化之后是否引用同一个对象,如果不是则说明初始化阶段创建了代理对象;如果是则说明初始化阶段没有创建代理对象;
               if (exposedObject == bean) {
                   //没有创建代理对象并不意味着最终结果是一个原始对象,代理有可能在二级缓存中提前创建了,所以要去二级缓存中取
                   exposedObject = earlySingletonReference;
               } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
                   String[] dependentBeans = this.getDependentBeans(beanName);
                   Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                   String[] var12 = dependentBeans;
                   int var13 = dependentBeans.length;

                   for(int var14 = 0; var14 < var13; ++var14) {
                       String dependentBean = var12[var14];
                       if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                           actualDependentBeans.add(dependentBean);
                       }
                   }

                   if (!actualDependentBeans.isEmpty()) {
                       throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
                   }
               }
           }
       }
       //...
   }

DefaultSingletonBeanRegistry#addSingletonFactory

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);
           //移除二级缓存中的Bean
           this.earlySingletonObjects.remove(beanName);
           this.registeredSingletons.add(beanName);
       }
   }
}

后处理器如何避免重复创建代理对象?

AbstractAutoProxyCreator#getEarlyBeanReference

public Object getEarlyBeanReference(Object bean, String beanName) {
    Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
    //如果提前创建代理,将代理放入earlyProxyReferences集合,如果集合中没有,则需要创建代理
    this.earlyProxyReferences.put(cacheKey, bean);
    return this.wrapIfNecessary(bean, beanName, cacheKey);
}
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
        //如果集合中已经缓存了代理,就不需要创建代理了,否则就需要在初始化阶段创建代理
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            return this.wrapIfNecessary(bean, beanName, cacheKey);
        }
    }

    return bean;
}

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        } else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        } else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
            Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
            if (specificInterceptors != DO_NOT_PROXY) {
                this.advisedBeans.put(cacheKey, Boolean.TRUE);
                Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
                this.proxyTypes.put(cacheKey, proxy.getClass());
                return proxy;
            } else {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return bean;
            }
        } else {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }
    }

2.2.构造器循环依赖

1>.表示通过构造器注入构成的循环依赖;

如:在创建TestA对象时,构造器需要TestB对象,那将去创建TestB对象,在创建TestB类时又发现需要依赖TestA对象,然后又要去创建TestA对象,…此时就陷入了一个死循环;

2>.示例代码如下:

public class A{
    private B b;
    private A(B b) {
            this.b = b;
        }
    //...
}

public class B{
    private A a;
    public  B(@Lazy TestA testA){
        this.testA=testA;
    }
    
    //...
}

3>.解决方案:
①.利用Spring三级缓存解决构造器注入造成的循环依赖问题?

根据上面的知识可以知道,三级缓存的重点思路是在对象实例创建之后将其放入三级缓存中(即singletonFactories),但是构造器循环依赖出现的时候对象实例还没有创建,因此不能使用三级缓存来解决构造器循环依赖问题!

②.利用@Lazy注解来解决构造器循环依赖问题?

@Log4j2
public class A {
    private B b;
    private A(@Lazy B b) {
        log.info("A()---{}",b.getClass());
        this.b = b;
    }
}

在这里插入图片描述

DefaultListableBeanFactory#resolveDependency

@Nullable
    public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
        descriptor.initParameterNameDiscovery(this.getParameterNameDiscoverer());
        if (Optional.class == descriptor.getDependencyType()) {
            return this.createOptionalDependency(descriptor, requestingBeanName);
        } else if (ObjectFactory.class != descriptor.getDependencyType() && ObjectProvider.class != descriptor.getDependencyType()) {
            if (javaxInjectProviderClass == descriptor.getDependencyType()) {
                return (new DefaultListableBeanFactory.Jsr330Factory()).createDependencyProvider(descriptor, requestingBeanName);
            } else {
                //进入到ContextAnnotationAutowireCandidateResolver#getLazyResolutionProxyIfNecessary
                Object result = this.getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);
                if (result == null) {
                    result = this.doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
                }

                return result;
            }
        } else {
            return new DefaultListableBeanFactory.DependencyObjectProvider(descriptor, requestingBeanName);
        }
    }

ContextAnnotationAutowireCandidateResolver#getLazyResolutionProxyIfNecessary

@Nullable
    public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, @Nullable String beanName) {
        //如果成员变量或者方法参数上加了'@Lazy'注解,创建代理对象
        return this.isLazy(descriptor) ? this.buildLazyResolutionProxy(descriptor, beanName) : null;
    }
protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, @Nullable final String beanName) {
    BeanFactory beanFactory = this.getBeanFactory();
    Assert.state(beanFactory instanceof DefaultListableBeanFactory, "BeanFactory needs to be a DefaultListableBeanFactory");
    final DefaultListableBeanFactory dlbf = (DefaultListableBeanFactory)beanFactory;
    //使用匿名内部类创建一个targetSource对象
    TargetSource ts = new TargetSource() {
       public Class<?> getTargetClass() {
                return descriptor.getDependencyType();
            }

            public boolean isStatic() {
                return false;
            }

            public Object getTarget() {
                Set<String> autowiredBeanNames = beanName != null ? new LinkedHashSet(1) : null;
                //当真正使用目标(依赖)对象时,才通过bean工厂间接获取目标对象,推迟了对目标对象的获取,从而解决循环依赖的问题
                Object target = dlbf.doResolveDependency(descriptor, beanName, autowiredBeanNames, (TypeConverter)null);
                if (target == null) {
                    Class<?> type = this.getTargetClass();
                    if (Map.class == type) {
                        return Collections.emptyMap();
                    } else if (List.class == type) {
                        return Collections.emptyList();
                    } else if (Set.class != type && Collection.class != type) {
                        throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(), "Optional dependency not present for lazy injection point");
                    } else {
                        return Collections.emptySet();
                    }
                } else {
                    if (autowiredBeanNames != null) {
                        Iterator var3 = autowiredBeanNames.iterator();

                        while(var3.hasNext()) {
                            String autowiredBeanName = (String)var3.next();
                            if (dlbf.containsBean(autowiredBeanName)) {
                                dlbf.registerDependentBean(autowiredBeanName, beanName);
                            }
                        }
                    }

                    return target;
                }
            }

            public void releaseTarget(Object target) {
            }
    };
    ProxyFactory pf = new ProxyFactory();
    pf.setTargetSource(ts);  //将一个自定义的对象添加到代理工厂中
    Class<?> dependencyType = descriptor.getDependencyType();
    if (dependencyType.isInterface()) {
        pf.addInterface(dependencyType);
    }

    //获取自定义对象的代理对象
    return pf.getProxy(dlbf.getBeanClassLoader());
}

因此,可以通过@Lazy注解注入一个代理对象来解决构造器循环依赖问题!

③.利用ObjectFactory来解决构造器循环依赖问题?

@Log4j2
public class A {
    private ObjectFactory<B> b;
    private A(ObjectFactory<B> b) {
        log.info("A()---{}",b.getClass());
        this.b = b;
    }
}

在这里插入图片描述

在注入依赖对象时候不注入真实的对象,而是注入一个ObjectFactory对象,延迟对象的获取,这样也可以解决构造器循环依赖问题!

④.利用java官方提供的Provider对象解决构造器循环依赖问题?

@Log4j2
public class A {
    private Provider<B> b;
    private A(Provider<B> b) {
        log.info("A()---{}",b.getClass());
        this.b = b;
    }
}

在这里插入图片描述

DefaultListableBeanFactory#resolveDependency

@Nullable
    public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
        descriptor.initParameterNameDiscovery(this.getParameterNameDiscoverer());
        if (Optional.class == descriptor.getDependencyType()) {
            return this.createOptionalDependency(descriptor, requestingBeanName);
        } else if (ObjectFactory.class != descriptor.getDependencyType() && ObjectProvider.class != descriptor.getDependencyType()) {
            //判断当前构造参数类型是否为javaxInjectProviderClass,如果是则通过Jsr330Factory()工厂创建一个provider对象
            if (javaxInjectProviderClass == descriptor.getDependencyType()) {
                return (new DefaultListableBeanFactory.Jsr330Factory()).createDependencyProvider(descriptor, requestingBeanName);
            } else {
                Object result = this.getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);
                if (result == null) {
                    result = this.doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
                }

                return result;
            }
        } else {
            return new DefaultListableBeanFactory.DependencyObjectProvider(descriptor, requestingBeanName);
        }
    }
private class Jsr330Factory implements Serializable {
        private Jsr330Factory() {
        }

       //创建一个provider工厂对象
        public Object createDependencyProvider(DependencyDescriptor descriptor, @Nullable String beanName) {
            return new DefaultListableBeanFactory.Jsr330Factory.Jsr330Provider(descriptor, beanName);
        }

        private class Jsr330Provider extends DefaultListableBeanFactory.DependencyObjectProvider implements Provider<Object> {
            public Jsr330Provider(DependencyDescriptor descriptor, @Nullable String beanName) {
                super(descriptor, beanName);
            }

            //当真正使用目标(依赖)对象时,才通过工厂对象间接获取目标对象,推迟了对目标对象的获取,从而解决循环依赖的问题
            @Nullable
            public Object get() throws BeansException {
                return this.getValue();
            }
        }
    }

利用java官方提供的Provider对象也可以解决构造器循环依赖问题,其原理和ObjectFactory类似!

⑤.利用@scope+@component注解解决构造器循环依赖问题?

@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) //在被依赖的对象上添加该注解
@Component
@Log4j2
public class B {
    private A a;

    public B(A a) {
        log.info("B()---{}",a);
        this.a = a;
    }
}

@Component
@Log4j2
public class A {
    private B b;

    private A(B b) {
        log.info("A()---{}",b);
        this.b = b;
    }
}

在这里插入图片描述

可以看到,这也是通过注入一个代理对象来解决构造器循环依赖问题!

如何选择?

ObjectFactory > Provider > @Lazy > @Scope ;

//工厂不会产生额外的代理对象,scope会产生额外的BeanDefinition以及往单例池中放额外的bean;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值