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;