欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring源码之循环依赖

程序员文章站 2022-10-03 20:10:59
https://www.cnblogs.com/longy2012/articles/12834762.htmlhttps://www.bilibili.com/video/BV1iD4y1o7pM?p=7https://www.jianshu.com/p/8bb67ca11831https://cloud.tencent.com/developer/article/1497692https://blog.nowcoder.net/n/2bb528b258b44c7eab1703a52170ef0....

https://www.cnblogs.com/longy2012/articles/12834762.html
https://www.bilibili.com/video/BV1iD4y1o7pM?p=7
https://www.jianshu.com/p/8bb67ca11831
https://cloud.tencent.com/developer/article/1497692
https://blog.nowcoder.net/n/2bb528b258b44c7eab1703a52170ef09

Spring源码之循环依赖

总结

  1. 在DefaultSingletonBeanRegistry类getSingleton方法中将beanName(a)加入到singletonsCurrentlyInCreation set集合中
  2. A进行实例化(未初始化)
  3. A加入三级缓存singletonFactories中
  4. 在AbstractAutowireCapableBeanFactory中populateBean方法中开始属性填充(field B)(调用AutowiredAnnotationBeanPostProcessor类中postProcessProperties方法)
  5. 在DefaultSingletonBeanRegistry类getSingleton方法中将beanName(b)加入到singletonsCurrentlyInCreation set集合中
  6. 将B加入singletonsCurrentlyInCreation,标志为正在创建中
  7. B进行实例化(未初始化)
  8. B加入三级缓存singletonFactories中
  9. 开始对B类进行属性填充(A field)
  10. 重新走到AbstractBeanFactory中doGetBean方法,调用DefaultSingletonBeanRegistry类getSingleton方法,将A put到二级缓存earlySingletonObjects中,并在三级缓存singletonFactories中移除
  11. B进行初始化
  12. getSingleton方法中调用DefaultSingletonBeanRegistry类afterSingletonCreation方法,将beanName(b)从singletonsCurrentlyInCreation移除
  13. 走到DefaultSingletonBeanRegistry中getSingleton方法finally中,将B加入一级缓存,并从三级缓存中移除
  14. 将B返回,A进行初始化
  15. getSingleton方法中调用DefaultSingletonBeanRegistry类afterSingletonCreation方法,将beanName(a)从singletonsCurrentlyInCreation移除
  16. 最后走到DefaultSingletonBeanRegistry中getSingleton方法finally中,将A加入一级缓存,并从二级缓存中移除

示例

  1. @DependsOn
@DependsOn("b")
@Component
public class A {
}

@DependsOn("a")
@Component
public class B {
}

报错:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'b' defined
  1. field属性注入循环依赖(不报错)
@Component
public class A {
    @Autowired
    private B b;
}

@Component
public class B {
    @Autowired
    private A a;
}

源码解析

三级缓存

DefaultSingletonBeanRegistry类中:

	/** 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 ConcurrentHashMap<>(16);

springboot中入口

调用链:
SpringApplication#run() --> SpringApplication#refreshContext() --> SpringApplication#refresh() --> ServletWebServerApplicationContext#refresh() --> AbstractApplicationContext#refresh() --> AbstractApplicationContext#finishBeanFactoryInitialization() --> DefaultListableBeanFactory#preInstantiateSingletons() --> AbstractBeanFactory#getBean() --> AbstractBeanFactory#doGetBean()

将beanName(a)加入到singletonsCurrentlyInCreation

AbstractBeanFactory#doGetBean()方法中:

if (!typeCheckOnly) {
	markBeanAsCreated(beanName);
}

markBeanAsCreated方法中:

this.alreadyCreated.add(beanName);

在getSingleton方法中,执行

beforeSingletonCreation(beanName);
this.singletonsCurrentlyInCreation.add(beanName)

其中singletonsCurrentlyInCreation为

/** Names of beans that are currently in creation. */
private final Set<String> singletonsCurrentlyInCreation =
		Collections.newSetFromMap(new ConcurrentHashMap<>(16));
A进行实例化(未初始化)

在在getSingleton方法执行到

singletonObject = singletonFactory.getObject();

调用匿名方法

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

调用AbstractAutowireCapableBeanFactory#createBean() --> AbstractAutowireCapableBeanFactory#doCreateBean(),执行如下代码进行实例化:

if (instanceWrapper == null) {
	instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();

bean(A)具备地址

A加入三级缓存singletonFactories中
// 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));
}
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);
		}
	}
}
在populateBean方法中开始对A属性填充
populateBean(beanName, mbd, instanceWrapper);
对B重复上面步骤

调用链

AbstractApplicationContext#refresh() --> AbstractApplicationContext#finishBeanFactoryInitialization() --> DefaultListableBeanFactory#preInstantiateSingletons() --> AbstractBeanFactory#getBean() --> AbstractBeanFactory#doGetBean() --> AbstractAutowireCapableBeanFactory#createBean()
–> AbstractAutowireCapableBeanFactory#doCreateBean()

(上面为A,下面开始A属性B注入)
–> AbstractAutowireCapableBeanFactory#populateBean() --> AutowiredAnnotationBeanPostProcessor#postProcessProperties() --> InjectionMetadata#inject() --> AutowiredAnnotationBeanPostProcessor#inject() --> DefaultListableBeanFactory#resolveDependency() --> DefaultListableBeanFactory#doResolveDependency() --> DependencyDescriptor#resolveCandidate() --> AbstractBeanFactory#getBean() --> AbstractBeanFactory#doGetBean()

会和上面A同样做下面这些操作:

  • 在DefaultSingletonBeanRegistry类getSingleton方法中将beanName(b)加入到singletonsCurrentlyInCreation set集合中
  • 将B加入singletonsCurrentlyInCreation,标志为正在创建中
  • B进行实例化(未初始化,具有B地址)
  • B加入三级缓存singletonFactories中
  • 开始对B类进行属性填充(A field)
将A put到二级缓存earlySingletonObjects中

重新对A执行doGetBean方法,执行getSingleton时,singletonFactory != null,故A放到二级缓存中,并从三级缓存中移除

Object sharedInstance = getSingleton(beanName);
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	// Quick check for existing instance without full singleton lock
	Object singletonObject = this.singletonObjects.get(beanName);
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		singletonObject = this.earlySingletonObjects.get(beanName);
		if (singletonObject == null && allowEarlyReference) {
			synchronized (this.singletonObjects) {
				// Consistent creation of early reference within full singleton lock
				singletonObject = this.singletonObjects.get(beanName);
				if (singletonObject == null) {
					singletonObject = this.earlySingletonObjects.get(beanName);
					if (singletonObject == null) {
						ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
						if (singletonFactory != null) {
							singletonObject = singletonFactory.getObject();
							this.earlySingletonObjects.put(beanName, singletonObject);
							this.singletonFactories.remove(beanName);
						}
					}
				}
			}
		}
	}
	return singletonObject;
}
B进行初始化

此时B完成属性注入,A具有地址,开始初始化:

// Initialize the bean instance.
Object exposedObject = bean;
try {
	populateBean(beanName, mbd, instanceWrapper);
	exposedObject = initializeBean(beanName, exposedObject, mbd);
}
将beanName(b)从singletonsCurrentlyInCreation移除

B执行完AbstractBeanFactory类匿名方法中createBean(beanName, mbd, args),接着getSingleton往下执行,在finally中:

finally {
	if (recordSuppressedExceptions) {
		this.suppressedExceptions = null;
	}
	afterSingletonCreation(beanName);
}
protected void afterSingletonCreation(String beanName) {
	if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
		throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
	}
}
将B加入一级缓存,并从三级缓存中移除

在getSingleton方法执行addSingleton(beanName, singletonObject);从而将B从三级缓存中移除,并添加到一级缓存中

protected void addSingleton(String beanName, Object singletonObject) {
	synchronized (this.singletonObjects) {
		this.singletonObjects.put(beanName, singletonObject);
		this.singletonFactories.remove(beanName);
		this.earlySingletonObjects.remove(beanName);
		this.registeredSingletons.add(beanName);
	}
}
完成A中B属性注入,对A进行初始化

A开始执行下面代码:

exposedObject = initializeBean(beanName, exposedObject, mbd);
开始将beanName(a)从singletonsCurrentlyInCreation移除;并从二级缓存中移除,添加到一级缓存

A接着getSingleton往下执行,在finally中执行afterSingletonCreation将beanName(a)从singletonsCurrentlyInCreation移除;
最后在addSingleton(beanName, singletonObject)将A从二级缓存中移除,添加到一级缓存

面试问题

  • 一级缓存是否够用?

不能。多线程情况下,会获取到实例化但没有初始化的对象,属性都为null

  • 二级缓存是否够用?

如果创建是普通类,二级缓存满足

  • 为什么需要三级缓存?(代理)

在动态代理中,返回是代理类。如果没有三级缓存,最开始放置是实例化好对象,然后缓存有了,后面进行代理处理,那原来的对象是否覆盖??

	/**
	 * Obtain a reference for early access to the specified bean,
	 * typically for the purpose of resolving a circular reference.
	 * @param beanName the name of the bean (for error handling purposes)
	 * @param mbd the merged bean definition for the bean
	 * @param bean the raw bean instance
	 * @return the object to expose as bean reference
	 */
	protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
		Object exposedObject = bean;
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
				}
			}
		}
		return exposedObject;
	}

本文地址:https://blog.csdn.net/weixin_43843104/article/details/109643586

相关标签: 技术