Spring源码分析:循环依赖

Spring在默认单例情况下是支持循环引用的。

1,什么是循环引用

@Component
public class BbService {

	@Autowired
	CcService ccService;

	public BbService() {
		System.out.println("constructor from BbService");
	}
}
@Component
public class CcService {

	@Autowired
	BbService bbService;

	public CcService() {
		System.out.println("constructor from CcService");
	}
}

这两个单例类互相引用,并且是非构造方法注入,就叫循环引用。

1,getBean(“bbService”)
2,getSingleton(“bbService”)=null
3,实例化bean,beanName=“bbService”
4,属性注入,populateBean(),beanName=“bbService”
5,发现依赖ccService
6,getBean(“ccService”)
7,getSingleton(“ccService”)=null
8,实例化bean,beanName=“ccService”
9,属性注入,populateBean(),beanName=“ccService”
10,发现依赖bbService
11,getBean(“bbService”)

这样就形成了死循环。
但是spring解决了这个问题。

2,解决循环引用

简单来说,spring是通过三级缓存来解决循环依赖的。
三级缓存其实就是三个map:

	/** Cache of singleton objects: bean name --> bean instance */
	//通常说的spring容器
	//实际上只是单例池
	//三级缓存之一:存放单例bean
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** Cache of singleton factories: bean name --> ObjectFactory */
	//三级缓存之一:存放ObjectFactory,单例对象的工厂
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** Cache of early singleton objects: bean name --> bean instance */
	//三级缓存之一:存放提前暴露的对象,没有经过完整的spring bean生命周期的bean
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

至于哪是一级,哪是二级,哪是三级,有很多种说法,我也不知道该怎么定,总之,知道这三个map的作用就行了。
接下来看spring是怎么通过三级缓存解决循环依赖的。
就以上文中的BbService和CcService为例来说明。
假设spring先初始化bbService,先从getBean(”bbService“)方法开始看。
getBean()方法什么也没干,就调用了doGetBean()方法

	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
		/**
		*  ....代码段
		*/

		// Eagerly check singleton cache for manually registered singletons.
		//从容器中取
		//第一次从容器中取,肯定为null
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			/**
			* ...代码段
			*/	
		}

				// Create bean instance.
				if (mbd.isSingleton()) {
					//重载方法
					//第二次从容器中取
					/**第二个参数是一个lamda表达式,类型是ObjectFactory
					 * 等价于
					 * class Temp implement ObjectFactory{
					 * 		@override
					 * 		public Object getObject(){
					 * 			createBean(beanName, mbd, args);
					 * 		}
					 *
					 * 		private Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
					 * 			.......
					 * 		}
					 * }
					 * ObjectFactory temp = new Temp();
					 * getSingleton(beanName, temp);
					 *
					 * 在getSingleton方法中调用第二个参数ObjectFactory的getObject()方法就是调用这里的createBean(beanName, mbd, args)方法
					 * */
					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;
						}
					});
						/**
						* ... 代码段
						*/
	}

bean初始化过程中,第一次调用getSingleton(beanName)返回结果肯定为null,因为此时bean还没有实例化。
重点看第二次的重载方法getSingleton(String beanName, ObjectFactory<?> singletonFactory)

	public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		synchronized (this.singletonObjects) {
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}
				//将beanName放入map中,singletonsCurrentlyInCreation,标识对应的bean正在创建中
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					//创建bean
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
					// Has the singleton object implicitly appeared in the meantime ->
					// if yes, proceed with it since the exception indicates that state.
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						throw ex;
					}
				}
				catch (BeanCreationException ex) {
					if (recordSuppressedExceptions) {
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					//bean创建完成后,将beanName从map:singletonsCurrentlyInCreation中移除
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					//将bean添加到单例池当中,
					//并且将对应的bean从三级缓存中移除
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

进入创建bean的方法singletonFactory.getObject()

	@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
		/**
		* ... 代码段
		*/
		try {
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isDebugEnabled()) {
				logger.debug("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		/**
		* ...代码段
		*/
	}
	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		/**
		* ...代码段
		*/
		if (instanceWrapper == null) {
			// 实例化bean
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		/**
		* ... 代码段
		*/

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		// 判断是否支持循环依赖
		// 如果支持,提前暴露bean,即将bean的工厂放入三级缓存中的singletonFactories
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			//第四次调用beanPostProcessor,SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		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);
			}
		}
		/**
		* ... 代码段
		*/
	}

核心方法:

	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);
				this.earlySingletonObjects.remove(beanName);
				this.registeredSingletons.add(beanName);
			}
		}
	}

这个方法在bean实例化之后,依赖注入之前调用,将没有完全初始化的bean的工厂放入三级缓存中的singletonFactories。
也就是说这个方法执行后,singletonFactories中会有一条数据,key=“bbService”。
然后调用populateBean(beanName, mbd, instanceWrapper)方法对bbService进行依赖注入,过程中发现依赖CcService,就会调用getBean(“ccService”)方法。
与bbService同样,在实例化之后,依赖注入之前,将没有完全初始化的bean的工厂放入三级缓存中的singletonFactories。
这时,singletonFactories中存在两条数据,key="bbService"和key=“ccService”。
然后调用populateBean(beanName, mbd, instanceWrapper)方法对ccService进行依赖注入,过程中发现依赖BbService,就会调用getBean(“bbService”)方法,这个时候与第一次调用getBean(“bbService”)就会有所不一样了。
第一次调用getBean(“bbService”)时,首先调用getSingleton(beanName)方法返回null,然后调用重载方法getSingleton(String beanName, ObjectFactory<?> singletonFactory)。
但是,这次调用getBean(“bbService”)时,调用getSingleton(beanName)方法的返回结果不再为null。先来看下这个getSingleton(beanName)方法。

	public Object getSingleton(String beanName) {
		return getSingleton(beanName, true);
	}
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		//从单例池中取
		Object singletonObject = this.singletonObjects.get(beanName);
		//是否正在创建中
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
			//从三级缓存中的earlySingletonObjects取
				singletonObject = this.earlySingletonObjects.get(beanName);
				//判断是否支持循环依赖
				if (singletonObject == null && allowEarlyReference) {
					//从三级缓存中的singletonFactories取bean工厂
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

三级缓存就是在这里发挥作用的。
1,从单例池singletonObjects中取”bbService“,肯定取不到,因为此时”bbService“还在依赖注入阶段,并没有被放入单例池当中
2,判断”bbService“是否正在创建中,返回结果为true,因为上文中有说道,在"bbService"实例化之前,会将beanName放入singletonsCurrentlyInCreation中。

	public boolean isSingletonCurrentlyInCreation(String beanName) {
		return this.singletonsCurrentlyInCreation.contains(beanName);
	}

3,从三级缓存中的earlySingletonObjects中取,依然取不到
4,判断是否支持循环依赖,allowEarlyReference是传入的参数,为true。
5,从三级缓存中的singletonFactories中取bean的工厂,此时能够取到"bbService"的bean工厂,因为上文已经说过,在bean实例化之后,依赖注入之前,会调用addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory)方法将bean的工厂放入singletonFactories
6,调用bean的工厂的getObject()方法,将结果放入三级缓存中的earlySingletonObjects,将bean的工厂从singletonFactories中移除,移除的原因是earlySingletonObjects中已经有了,就不会再从singletonFactories中取了(至于为什么在放入singletonFactories时不直接调用getObject()方法,将结果放入earlySingletonObjects,这样就不需要singletonFactories了,我也没搞清楚)。
到这里,循环依赖的问题已经基本解决了。

1,getBean(“bbService”)
2,getSingleton(“bbService”)=null
3,singletonsCurrentlyInCreation.add(“bbService”)
4,实例化bean,beanName=“bbService”
5,将bean的工厂放入singletonFactories,beanName=“bbService”
6,属性注入,populateBean(),beanName=“bbService”
7,发现依赖ccService
8,getBean(“ccService”)
9,getSingleton(“ccService”)=null
10,singletonsCurrentlyInCreation.add(“ccService”)
11,实例化bean,beanName=“ccService”
12,将bean的工厂放入singletonFactories,beanNaem=“ccService”
13,属性注入,populateBean(),beanName=“ccService”
14,发现依赖bbService
15,getBean(“bbService”)
16,getSingleton(“bbService”)
17,objectFactory=singletonFactories.get(“bbService”)
18,object=objectFactory.getObject()
19,earlySingletonObjects.put(“bbService”,object),singletonFactories.remove(“bbService”)
20,"ccService"依赖注入成功
21,"ccService"初始化完成
22,singletonsCurrentlyInCreation.remove(“ccService”)
23,singletonObjects.put(“ccService”,ccService),earlySingletonObjects.remove(“ccService”)
24,"bbService"依赖注入成功
25,"bbService"初始化完成
26,singletonsCurrentlyInCreation.remove(“bbService”)
27,singletonObjects.put(“bbService”,bbService),earlySingletonObjects.remove(“bbService”)

3,循环引用是的aop

但是,注意,但是,特殊情况来了:
在上一篇BeanPostProcessor的文章中讲过,spring的aop是在第八次调用BeanPostProcessor时完成代理的,这个步骤实在依赖注入之后的

	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		/**
		* ... 代码段
		*/

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			//属性注入
			populateBean(beanName, mbd, instanceWrapper);
			//这个方法中第七次和第八次调用BeanPostProcessor,完成bean的初始化和aop代理
			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);
			}
		}

		/**
		* ... 代码段
		*/

		return exposedObject;
	}

那么问题来了,按照这个逻辑,在上文循环依赖的过程中,ccService中注入的bbService应该是bbService的原生对象,那么在bbService有aop的情况下,ccService中的属性bbService是什么时候被替换成bbService的代理对象的呢?

@Component
@Aspect
public class MyAspect {

	@Pointcut("within(com.andy.service.BbService)")
	public void pointcut(){}

	@Before("pointcut()")
	public void before(){
		System.out.println("aop-----before");
	}
}
@Component
public class BbService {

	@Autowired
	CcService ccService;

	public BbService() {
		System.out.println("constructor from BbService");
	}

	public void aop(){
		System.out.println("AaService----aop");
	}
}

经过debug发现,在上文的循环依赖过程中,ccService在进行依赖注入的时候,注入的就是bbService的代理对象
在这里插入图片描述
这又是怎么回事呢?
debug发现,在上文第18步中objectFactory.getObject()返回的就是代理对象。
在进入objectFactory.getObject()方法研究之前,还记得上文的第5步:将bean的工厂放入singletonFactories,beanName="bbService"吗?

	/**第二个参数是一个lamda表达式,类型是ObjectFactory
	 * 等价于
	 * class Temp implement ObjectFactory{
	 * 		@override
	 * 		public Object getObject(){
	 * 			getEarlyBeanReference(beanName, mbd, args);
	 * 		}
	 *
	 * 		private Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
	 * 			.......
	 * 		}
	 * }
	 * ObjectFactory temp = new Temp();
	 * getSingleton(beanName, temp);
	 *
	 * 当调用objectFactory.getObject()时,实际上调用的就是这个getEarlyBeanReference(beanName, mbd, bean)方法
	 * */
	addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

直接进入getEarlyBeanReference(beanName, mbd, bean)方法

	protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
		Object exposedObject = bean;
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			//getBeanPostProcessors()方法的结果中有一个AbstractAutoProxyCreator,完成aop的类
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
				}
			}
		}
		return exposedObject;
	}

这里就是BeanPostProcessor中讲到的第四次调用。
进入AbstractAutoProxyCreator的getEarlyBeanReference(exposedObject, beanName)方法,这个方法的作用就是提前完成aop并将bean记录在earlyProxyReferences中

	@Override
	public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		//将提前完成aop的bean记录下来
		this.earlyProxyReferences.put(cacheKey, bean);
		//真正完成aop的方法
		return wrapIfNecessary(bean, beanName, cacheKey);
	}

所以objectFactory.getObject()返回的就是代理对象。
然后在BeanPostProcessor的第八次调用时,调用到AbstractAutoProxyCreator的postProcessAfterInitialization(bean,beanName)时,首先判断earlyProxyReferences中是否存在bean,如果存在,说明已经完成aop了,就直接返回,如果不存在,再进行aop,然后返回。

	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			//判断earlyProxyReferences中是否存在该bean
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

所以循环依赖的情况下,aop是会提前完成的。

4,关闭循环引用

本文第一句话说道:Spring在默认单例情况下是支持循环引用的。
那么在什么情况下不支持循环依赖呢?
在bean实例化完成后,将bean的工厂放入singletonFactories之前,有一个if判断

// 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));
		//条件为true时,才会将bean的工厂放入singletonFactories
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			//第四次调用beanPostProcessor,SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

earlySingletonExposure的值由三个条件决定:
1,mbd.isSingleton(),这个一定为true,现在研究的就是单例bean的循环依赖,只有单例bean才会存在循环依赖。
2,this.allowCircularReferences
3,isSingletonCurrentlyInCreation(beanName)这个也一定为true,因为上文循环依赖的第三步。
所以关键就看this.allowCircularReferences,这是AbstractAutowireCapableBeanFactory中的一个私有属性,默认为true,spring中也没有地方修改这个值,所以说spring默认支持循环依赖。

	/** Whether to automatically try to resolve circular references between beans */
	private boolean allowCircularReferences = true;

但是spring也提供了api来修改这个值

public class Test {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
		//一定要在refresh()方法之前设置,因为refresh()结束后,bean都初始化完了,在设置就没有意义
		ac.setAllowCircularReferences(false);
		ac.register(AppConfig.class);
		ac.refresh();
	}
}

运行结果如下:

警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bbService': Unsatisfied dependency expressed through field 'ccService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'ccService': Unsatisfied dependency expressed through field 'bbService'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'bbService': Requested bean is currently in creation: Is there an unresolvable circular reference?
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bbService': Unsatisfied dependency expressed through field 'ccService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'ccService': Unsatisfied dependency expressed through field 'bbService'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'bbService': Requested bean is currently in creation: Is there an unresolvable circular reference?
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:586)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:372)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1353)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:583)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:500)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:229)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:890)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:556)
	at com.andy.test.Test.main(Test.java:21)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'ccService': Unsatisfied dependency expressed through field 'bbService'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'bbService': Requested bean is currently in creation: Is there an unresolvable circular reference?
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:586)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:372)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1353)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:583)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:500)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:229)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:251)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1131)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1058)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:583)
	... 13 more
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'bbService': Requested bean is currently in creation: Is there an unresolvable circular reference?
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:349)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:221)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:251)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1131)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1058)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:583)
	... 26 more

spring应该是没有提供通过配置关闭循环依赖的方式,所以只能通过编码的方式。
实际开发中也应该没人闲的蛋疼去关闭循环依赖,这里写出来只是为了加深对循环依赖源码的研究。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值