Spring循环依赖源码解析

构造器循环依赖

示例

@Component
public class RoleService {

    private UserService userService;

    public RoleService(UserService userService) {
        this.userService = userService;
    }
}
@Component()
public class UserService {

    private RoleService roleService;

    public UserService(RoleService roleService) {
        this.roleService = roleService;
    }
}

结果

BeanCurrentlyInCreationException
该问题无法解决
具体分析参照下面

field循环依赖

默认singleton

示例

@Component
public class RoleService {

    @Autowired
    private UserService userService;
    
    public void test() {
        System.out.println("RoleService->" + userService);
    }
}
@Component()
public class UserService {

    @Autowired
    private RoleService roleService;

    public void test() {
        System.out.println("UserService->" + roleService);
    }
}

结果

可以成功创建,并自动注入

Spring对循环依赖的处理方案

创建Bean的简要流程,以上面示例代码为例

  1. 检测到要创建roleService
  2. 调用无参构造,实例化
  3. 检测到依赖userService
  4. 将bean"roleService"标志为创建中的状态,并将已经实例化的roleService放到缓存(map)中
  5. 去beanFactory中去获取userService
  6. 没有获取到,就回去创建
  7. 调用userService的无参构造,实例化
  8. 检测到依赖roleService
  9. 去缓存(map)中查找,获取到roleService,并注入
  10. userService初始化完成
  11. 从beanFactory中获取userService,并注入roleService
  12. roleService初始化完成

源码分析

我们从AnnotationConfigApplicationContext的构造方法进入,
在refresh()方法中

// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

然后进入到

// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();

其中,显然不是FactoryBean,所以会进入else里的getBean(beanName)

// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						final FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
											((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				else {
					getBean(beanName);
				}
			}
		}

进入方法,最后会进入到doGetBean方法,第一次,显然还没有实例化bean,上面的判断会跳过,会先执行如下方法

// Create bean instance.
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;
		}
	});
	bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

然后会进入其中的createBean(beanName, mbd, args),进入到doCreateBean方法,以下就会完成roleService的实例化,但是此时其中的成员变量userService还是null

// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = instanceWrapper.getWrappedInstance();

接下来会执行到如下代码

		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));
		}

进入addSingletonFactory,可以看到Spring会把已经实例化的roleService存储到singletonFactories中,registeredSingletons中仅存储的beanName

	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);
			}
		}
	}

回到doCreateBean方法

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}

进入populateBean方法,进入如下循环,当循环到AutowiredAnnotationBeanPostProcessor时,此时就可以进入他的postProcessProperties方法

		if (hasInstAwareBpps) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						if (filteredPds == null) {
							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
						}
						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvsToUse == null) {
							return;
						}
					}
					pvs = pvsToUse;
				}
			}
		}

进入postProcessProperties方法

try {
	metadata.inject(bean, beanName, pvs);
}

进入到inject方法,此时的beanName就是第一次创建的bean的成员变量,是userService,此时就会去进行userService初始化

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
	Collection<InjectedElement> checkedElements = this.checkedElements;
	Collection<InjectedElement> elementsToIterate =
			(checkedElements != null ? checkedElements : this.injectedElements);
	if (!elementsToIterate.isEmpty()) {
		for (InjectedElement element : elementsToIterate) {
			if (logger.isTraceEnabled()) {
				logger.trace("Processing injected element of bean '" + beanName + "': " + element);
			}
			element.inject(target, beanName, pvs);
		}
	}
}

源码嵌套很多,这里就不贴了,之后还是会进入doGetBean方法,然后和上面类似,调用无参构造,完成userService的实例化,然后依然会去进行注入,这时,就会从上面的singletonFactories中找到已经完成实例化的roleService,完成注入,userService初始化完成,之后再执行完成就会顺利完成对roleService的注入

prototype

如果将以上的userService和roleService任意一个变为prototype,都可以完成注入
但如果两者同时变为prototype,就会抛出BeanCurrentlyInCreationException
由于没有具体应用场景,就不分析了

结论

构造器循环依赖Spring无法解决
singleton的成员变量的循环依赖可以解决,prototype的不行

补充一: beanFactory.getBean()是很强大的方法,其中可以获取容器中的bean,也可以初始化懒加载的bean,也可以每次初始化prototype的bean
补充二:如果是singleton的bean依赖prototype的bean,使用@Lookup就可以每次获取新的prototype的bean,不做任何处理的话,这个bean就会使单例的

发布了37 篇原创文章 · 获赞 1 · 访问量 1053

猜你喜欢

转载自blog.csdn.net/zhuchencn/article/details/103924410