spring源码解析之循环依赖处理

简单解释循环依赖

循环依赖就是class A依赖class B,同时class B依赖class A,更多的class互相依赖类似。

spring无法处理的情形

显然scope为prototype的bean是无法解决的,每次都要new新的bean,还要互相依赖,就像死锁一样。

只提供一个属性注入的构造器同样无法解决循环依赖,原因同prototype,注意这里指A只有一个构造方法,构造方法参数为B,这样是无法实例化的。如果A还提供了空的构造方法,那是可以完成实例化的。

so,spring只解决singleton bean的循环依赖,那是怎么解决的呢?显然问题出在实例化的时候,如果先实例化,然后再进行属性注入是可以的。

比如,可以先实例化A和B,然后在A中需要B时,通过getBean的方式获取B,同理在B中使用getBean获取A。spring也是如此,提前曝光bean,然后装配。

测试代码

@Service
public class ServiceA {
    
    
    @Autowired
    private ServiceB serviceB;

@Service
public class ServiceB {
    
    
    @Autowired
    private ServiceA serviceA;

@Configuration
@ComponentScan(value = "com.star.xxx")
public class BeanTestConfig {
    
    
}

public class BeanTest {
    
    
    public static void main(String[] args) {
    
    
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanTestConfig.class);
		context.getBean("serviceA",ServiceA.class);
    }
}

源码跟读

在spring中bean创建都是从doGetBean()开始的,可以在getBean()方法处断点进入,然后会看到Object sharedInstance = getSingleton(beanName);具体代码如下:

@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    
    
	Object singletonObject = this.singletonObjects.get(beanName);
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    
    
		synchronized (this.singletonObjects) {
    
    
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
    
    
				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
    
    
					singletonObject = singletonFactory.getObject();
					this.earlySingletonObjects.put(beanName, singletonObject);
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
	return singletonObject;
}

三个map集合如下,用来缓存bean实例或ObjectFactory:

/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

第一次创建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);
}

中间实例化bean暂时省略,然后向缓存singletonFactories中添加ObjectFactory:

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

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

实例完成后,开始init操作,组装bean:

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

然后调用各种beanPostProcessor,这里使用的是@Autowired注解,对应的AutowiredAnnotationBeanPostProcessor,获取B实例,同样从doGetBean()开始。

不同的是初始化B时,singletonFactories中已经有了A的ObjectFactory,ObjectFactory类似FactoryBean包装了一下目标实例。

接着调用ObjectFactory的getObject方法返回目标实例,放入earlySingletonObjects中,同时移除ObjectFactory用完即除,然后B就成功初始化了,B就放到了缓存singletonObjects。

有了B此时A也可以成功初始化了,A也放到singletonObjects中,缓存earlySingletonObjects中的A也可以删除了。毕竟最终是要放到singletonObjects中的,其他两个map缓存只是为了临时缓存用来解决循环依赖的问题,这也是为什么map的初始化容量差别所在。

以上就是spring解决循环依赖的基本流程了,其实spring的创建bean的流程也是这么走下来的。

觉得有用,点个关注。如有纰漏,欢迎批评指正。

同名公众号:码农小麦
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43275277/article/details/108000708
今日推荐