创建 A 实例时需要 B,创建 B实例时需要 A。
测试环境:https://gitee.com/jhxxb/MySpringBoot/tree/master/Spring-Base/src/test/java/BeanCircularDependency
Spring IOC 中 Bean 的作用域有多种:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-scopes
默认 Bean 作用域为单例模式,Spring 解决循环依赖只能解决单例模式下的,无法解决多实例循环依赖,因为每次都需要 new,无法使用缓存
单例模式下也无法解决构造器方式注入的循环依赖,必须要有一个 Bean 不是构造器注入
总的来说 Spring 只能解决单例模式下的非构造器注入的循环依赖问题
注:Spring Boot 2.6.0 开始循环引用默认是被禁用的(只是 Spring Boot 默认禁止了,Spring Framework 默认还是允许)
可以配置开启
spring.main.allow-circular-references=true
前置知识
先清楚 Spring 中的两个概念
- 实例化:就是 new 一个对象
- 初始化:给 new 的对象设置属性
还需要了解下 Spring IOC 中的三级缓存,平常所说的 IOC 容器就是一个 ConcurrentHashMap
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
/**
* 一级缓存,单例对象的缓存:bean名称-bean实例,存放生成好的单例 Bean
*/
private final Map singletonObjects = new ConcurrentHashMap<>(256);
/**
* 三级缓存,单例工厂的缓存:bean名称-ObjectFactory,存放生成 bean 的工厂
*/
private final Map> singletonFactories = new HashMap<>(16);
/**
* 二级缓存,早期的单例对象的缓存:bean名称-bean实例,存放实例化但未初始化(Bean 的属性还未填充)的单例 bean
*/
private final Map earlySingletonObjects = new ConcurrentHashMap<>(16);
过程,分三步
- A 创建过程中需要 B,于是 A 将自己放到三级缓里面,去实例化 B
- B 实例化的时候发现需要 A,于是 B 先查一级缓存,没有,再查二级缓存,还是没有,再查三级缓存,找到了 A,然后把三级缓存里面的这个 A 放到二级缓存里面,并删除三级缓存里面的 A
- B 顺利初始化完毕,将自己放到一级缓存里面(此时 B 里面的 A 依然是创建中状态),然后回来接着创建 A,此时 B 已经创建结束,A 直接从一级缓存里面拿到 B,然后 A 完成创建,并将 A 自己放到一级缓存里面。
源码(已删除部分影响阅读的代码,主要看处理流程)
从获取对象开始,开始创建 A 对象,其实就是 IOC 的初始化流程:https://www.cnblogs.com/jhxxb/p/13609289.html
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
@Override
public void preInstantiateSingletons() throws BeansException {
List beanNames = new ArrayList<>(this.beanDefinitionNames);
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) { // 是否为工厂 Bean
} else {
getBean(beanName); // 获取 Bean 对象
}
}
}
进入到 getBean(beanName) 获取 Bean
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
@SuppressWarnings("unchecked")
protected T doGetBean(String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else { // 没有获取到 A 对象,会进入到这里
if (isPrototypeCurrentlyInCreation(beanName)) { // 检查正在创建中的 Bean 是否包含 A,如果是那就抛异常(循环依赖)
throw new BeanCurrentlyInCreationException(beanName);
}
try {// 是否有 Bean 需要在 A 之前创建
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
}
if (mbd.isSingleton()) { // 创建单例模式 Bean
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) { // 创建原型模式 Bean
} else { // 其它 scope 类型的处理
}
}
}
return adaptBeanInstance(name, beanInstance, requiredType);
}
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
@Override
@Nullable
public Object getSingleton(String beanName) { // 去容器中拿 Bean,有则直接返回
return getSingleton(beanName, true);
}
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName); // 获取单例 Bean
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { // 是否正在创建中
}
return singletonObject; // A 没有创建过,直接到这里
}
public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
beforeSingletonCreation(beanName); // singletonsCurrentlyInCreation 把它添加进去,证明这个 Bean 正在创建中
boolean newSingleton = false;
try {
singletonObject = singletonFactory.getObject(); // 创建 Bean
newSingleton = true;
} catch (IllegalStateException ex) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
} finally {
afterSingletonCreation(beanName);
}
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
进入到 createBean(beanName, mbd, args) 开始创建 Bean
public abstract class AbstractAutowireCapableBeanFactory extends org.springframework.beans.factory.support.AbstractBeanFactory implements AutowireCapableBeanFactory {
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
try {
// 给 Bean 一个返回代理对象的机会
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args); // 创建 Bean
return beanInstance;
}
}
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args); // 创建 Bean 实例
}
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) { // 放入三级缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
try {
populateBean(beanName, mbd, instanceWrapper); // 属性填充,其中会实例化 B
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
return exposedObject;
}
@SuppressWarnings("deprecation")
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (hasInstAwareBpps) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
// 关于 postProcessPropertyValues 的实现,有几个处理器是非常关键的:
// 如 AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor 等
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
}
public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
@Deprecated
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
return postProcessProperties(pvs, bean, beanName);
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
}
return pvs;
}
private class AutowiredFieldElement extends InjectedElement {
@Override
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 {
try {
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); // 获取 B 对象
}
}
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value); // 设置实例对象 A 的属性 B
}
}
}
}
public class InjectionMetadata {
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection checkedElements = this.checkedElements;
Collection elementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
element.inject(target, beanName, pvs); // AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement#inject
}
}
}
}
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
if (Optional.class == descriptor.getDependencyType()) {
} else if (ObjectFactory.class == descriptor.getDependencyType() || ObjectProvider.class == descriptor.getDependencyType()) {
} else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
} else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); // 解析依赖 B
}
return result;
}
}
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this); // 获取依赖的实例对象
}
Object result = instanceCandidate;
return result;
}
}
}
public class DependencyDescriptor extends InjectionPoint implements Serializable {
public Object resolveCandidate(String beanName, Class requiredType, BeanFactory beanFactory) throws BeansException {
return beanFactory.getBean(beanName); // 又回到了 getBean 方法获取实例 B
}
}
创建 B 实例时同样会走到 DependencyDescriptor#resolveCandidate 来又创建 A,看 Spring 是怎么处理的
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
@SuppressWarnings("unchecked")
protected T doGetBean(String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
String beanName = transformedBeanName(name);
Object beanInstance;
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) { // 可以获取到 A 对象
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
}
return adaptBeanInstance(name, beanInstance, requiredType);
}
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
@Override
@Nullable
public Object getSingleton(String beanName) { // 去容器中拿 Bean,有则直接返回
return getSingleton(beanName, true);
}
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName); // 从一级缓存中获取单例 Bean
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { // 是否正在创建中
// 会进入到这里,A 确实是正在创建中
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
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(); // 获取未赋属性值的 A 对象
this.earlySingletonObjects.put(beanName, singletonObject); // 将 A 加入到二级缓存
this.singletonFactories.remove(beanName); // 把 A 从三级缓存中移除
}
}
}
}
}
}
return singletonObject; // 返回未赋属性值的 A 对象
}
继续看 B 对象的创建,它会在 A 对象之前创建出来
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
beforeSingletonCreation(beanName); // singletonsCurrentlyInCreation 把它添加进去,证明这个 Bean 正在创建中
boolean newSingleton = false;
try {
singletonObject = singletonFactory.getObject(); // 创建 B 对象完成
newSingleton = true;
} finally {
afterSingletonCreation(beanName); // 从 singletonsCurrentlyInCreation 中移除
}
// 若是新创建的 Bean,那就执行 addSingleton 方法
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
protected void addSingleton(String beanName, Object singletonObject) { // Bean 彻底创建完成,添加进 singletonObjects
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject); // 把实例 B 放入一级缓存,B 直接从三级缓存到了一级缓存
this.singletonFactories.remove(beanName); // 从三级缓存中删除
this.earlySingletonObjects.remove(beanName); // 从二级缓存中删除
this.registeredSingletons.add(beanName); // 记录已经创建好的 Bean 的名称,有顺序
}
}
之后 A 会像 B 一样被创建出来。
回到最开始,A 创建完后会继续创建 B,但这时就不会再走创建流程了,直接可以获取到 B
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
@Override
public void preInstantiateSingletons() throws BeansException {
List beanNames = new ArrayList<>(this.beanDefinitionNames);
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) { // 是否为工厂 Bean
} else {
getBean(beanName); // 可以直接获取到 B 对象,没有了后续的创建流程
}
}
}
Spring 中加入三级缓存的代码
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
}
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { // 从创建工厂中获取实例对象,会对 Bean 进行一些处理
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
protected void addSingletonFactory(String beanName, ObjectFactory singletonFactory) {
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory); // 加入三级缓存,是创建工厂,并非实例对象
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
图示
关闭 Spring 的循环依赖
查看源码可以发现有一个 allowCircularReferences 属性可以控制
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
/** Whether to automatically try to resolve circular references between beans. */
private boolean allowCircularReferences = true;
https://blog.csdn.net/f641385712/article/details/92801300
Original: https://www.cnblogs.com/jhxxb/p/14421578.html
Author: 江湖小小白
Title: Spring Bean 循环依赖
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/540329/
转载文章受原作者版权保护。转载请注明原作者出处!