spring怎么解决循环依赖?

我们知道spring在创建bean的整个周期过程当中,会出现循环依赖问题 我们先拿出一个demo

我们创造出TestService和UserService之间有循环依赖

TestService:

package com.test.autowired.service;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class TestService {

    //TestService 里面需要UserService 对象
	@Autowired
	UserService userService;

	public TestService() {
		System.out.println("TestService---------------无参构造器创建对象");
	}

	//bean创建完好后的回调
	@PostConstruct
	public void after(){
		System.out.println("TestService------------------bean初始化完后的回调");
	}
}

UserService:

package com.test.autowired.service;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class UserService {

	//UserService 里面需要testService
	@Autowired
	TestService testService;

	public UserService() {
		System.out.println("UserService---------------无参构造器创建对象");
	}

	@PostConstruct
	public void after(){
		System.out.println("UserService------------------bean初始化完后的回调");
	}
}

上面两个类 在spring启动容器加载的时候 就会出现循环依赖问题  那么我们的spring是怎么去解决的呢?

无论是先初始化完TestService还是先初始化UserService  都需要对方的属性填充 才能完成bean的整个生命周期

下面我们来看看源码

我们直接来看finishBeanFactoryInitialization(beanFactory);这个方法才是完成bean整个初始化过程

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// Initialize conversion service for this context.
		//首先,初始化名字为 conversionService 的 Bean。
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
			beanFactory.setConversionService(
					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
		}

		// Register a default embedded value resolver if no bean post-processor
		// (such as a PropertyPlaceholderConfigurer bean) registered any before:
		// at this point, primarily for resolution in annotation attribute values.
		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(strVal ->     getEnvironment().resolvePlaceholders(strVal));
		}
        // Initialize LoadTimeWeaverAware beans early to allow for registering their                     transformers early.
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}

		// Stop using the temporary ClassLoader for type matching.
		beanFactory.setTempClassLoader(null);

		// Allow for caching all bean definition metadata, not expecting further changes.
		// 没什么别的目的,因为到这一步的时候,Spring 已经开始预初始化 singleton beans 了,
		// 肯定不希望这个时候还出现 bean 定义解析、加载、注册。
		beanFactory.freezeConfiguration();

		// Instantiate all remaining (non-lazy-init) singletons.
		// 开始初始化剩下的单实例bean
		beanFactory.preInstantiateSingletons();
	}
        

中间我们省略  直接看    beanFactory.preInstantiateSingletons();这个方法  我们直接进入getBean(beanName)调用的doGetBean方法

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
      @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
   final String beanName = transformedBeanName(name);
 
  Object bean;
  Object sharedInstance = getSingleton(beanName);
   if (sharedInstance != null && args == null) {
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }
   else {
      //prototypesCurrentlyInCreation 需要联系 getSingleton方法
      if (isPrototypeCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(beanName);
      }else{
               if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName, () -> {
               try {
                  return createBean(beanName, mbd, args);
               }
               catch (BeansException ex) {
                  destroySingleton(beanName);
                  throw ex;
               }
            });
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
         }
   return (T) bean;
}

代码过长 我们这里只贴出部分代码 第一次我们调用 getSingleton(beanName) 来获取bean对象 spring容器刚初始化这个时候

肯定为空 所以我们就会走进第二次调用 sharedInstance = getSingleton(beanName, () -> { try {return createBean(beanName, mbd, args);}  这个是方法的重载  那么我们就进入getSingleton这个重载方法里面

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");

		//预创建bean对象
		beforeSingletonCreation(beanName);
        singletonObject = singletonFactory.getObject();
		newSingleton = true;
                

首先我们会进入beforeSingletonCreation(beanName);

if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);  }

假设我们先初始化TestSservice的bean,这个方法是将会把testService放入singletonsCurrentlyInCreation这个set里面  表示这个

beanName是将要创建的,完成beforeSingletonCreation 我们继续看    singletonObject = singletonFactory.getObject();

这里完成了一个回调  会回到我们的return createBean(beanName, mbd, args); 我们开始创建bean 我们直接进入createBean方法开面的Object beanInstance = doCreateBean(beanName, mbdToUse, args)方法

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

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			//开始实例化对象 而不是bean 就是new
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}
        // Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}
        // 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));

		//此处解决循环依赖
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

         // Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			//代理对象入口
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		

		}
        
 return exposedObject;

上面也是贴出核心部分  首先我们的实例化出对象(注意对象bean是两个不同的概念)

            //开始实例化对象 而不是bean 就是new
            instanceWrapper = createBeanInstance(beanName, mbd, args); 这里通过反射实例化的是TestService对象

下面这个方法则是提供后置处理器进行处理AutowiredAnnotationBeanPostProcessor

 

    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));  这里判断是否是单列  是否允许循环依赖(默认为true) 并且是否是正在创建中              由上面的分析这个earlySingletonExposure 得到的为true  则就调用下面的

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean))  将我们上面创建的对象放在二级缓存里面

下面这个方法populateBean(beanName, mbd, instanceWrapper)将是对对象进行填充 (这里就会出现自动注入 开始出现循环依赖的问题) 我们进入方法

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
	PropertyDescriptor[] filteredPds = null;
		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;
				}
			}
		}
}

我们省略 直接进入核心

    PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); 这里会调用AutowiredAnnotationBeanPostProcessor后置处理器的实现

	@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
		try {
			metadata.inject(bean, beanName, pvs);
		}
		catch (BeanCreationException ex) {
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
		}
		return pvs;
	}

我们会看到AutowiredAnnotationBeanPostProcessor的postProcessProperties填充属性的时候回调用metadata.inject(bean, beanName, pvs); 自动注入的方法 我们进入inject()方法  

	protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
			Field field = (Field) this.member;
			Object value;
			if (this.cached) {
				value = resolvedCachedArgument(beanName, this.cachedFieldValue);
			}
			else {
				DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
				desc.setContainingClass(bean.getClass());
				Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
				Assert.state(beanFactory != null, "No BeanFactory available");
				TypeConverter typeConverter = beanFactory.getTypeConverter();
				try {
					value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
				}
......
.....
...

我们可以看我们的bean工厂处理这层依赖关系  我们看value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); 点进去 我们发现我们又回到了大家数据的DefaultListableBeanFactory这个类中

@Override
	@Nullable
	public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

		descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
		if (Optional.class == descriptor.getDependencyType()) {
			return createOptionalDependency(descriptor, requestingBeanName);
		}
		else if (ObjectFactory.class == descriptor.getDependencyType() ||
				ObjectProvider.class == descriptor.getDependencyType()) {
			return new DependencyObjectProvider(descriptor, requestingBeanName);
		}
        else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
			return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
		}
		else {
			Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
					descriptor, requestingBeanName);
			if (result == null) {
				result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
			}
			return result;
		}
	}

直接看最后处理方法result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);

点进去 我们找到最后的

if (instanceCandidate instanceof Class) {
                instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
            }  到此你会发现  我们又进入了beanFactory.getBean(beanName);  getBean的方法  但是这里的是获取带有注解的bean 也就是我们这里的userService 这样我们又回到原点去getSingtonObject().....等等一系列的操作

 就上面做个总结:

假如我们a注入了b   b也注入了a  那么spring容器初始化的时候 假如是先初始化A,初始化的过程中在AbstractAutowireCapableBeanFactory的doCreateBean方法中先会创建a的对象(利用反射)创建完对象后 给该对象填充属性,这时候会发现b这个对象并不存在,那么根据判断调用AutowiredAnnotationBeanPostProcessor后置处理器去处理b的bean的初始化的过程  这个时候就会来初始化b  初始化b的整个过程中 发现需要a对象  由于前面我们已经创建了a对象放在了二级缓存当中,这里b就可以直接去取出来 完成对应的初始化工作, 等b的bean初始化完成之后a陆续完成对应的初始化工作。

我们暂时对着源码分析到这里  当然这里有很多细节  需要我们对着源码断点分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值