Spring之【循环引用】

发布于:2025-08-02 ⋅ 阅读:(12) ⋅ 点赞:(0)

目录

前置知识

        SingletonBeanRegistry

        DefaultSingletonBeanRegistry

Spring中处理循环引用的流程分析

        定义两个具有循环引用特点的Bean

        执行A的实例化

        执行A的属性填充(执行过程中发现A依赖B,就去执行B的实例化逻辑)

        执行B的实例化

        执行B的属性填充

        执行B的初始化

        执行A的属性填充(此时依赖的B已经完成了实例化和初始化放到容器的单例池中,接着执行之前没有执行完成的A的属性填充逻辑)

        执行A的初始化


前置知识

SingletonBeanRegistry

该接口中定义了一些和单例Bean有关的方法

package org.springframework.beans.factory.config;

public interface SingletonBeanRegistry {

    /**
     * 往容器中添加单例bean对象
     */
	void registerSingleton(String beanName, Object singletonObject);

    /**
     * 通过bean名字获取bean对象
     */
    Object getSingleton(String beanName);
    
    /**
     * 判断容器中是否包含某bean名字的单例bean
     */
	boolean containsSingleton(String beanName);

    /**
     * 获取容器中所有单例bean的名称集合
     */
	String[] getSingletonNames();

    /**
     * 获取容器中单例bean对象的数量
     */
	int getSingletonCount();
}

DefaultSingletonBeanRegistry

  • 定义了三个Map集合(也就是常说的三级缓存)
  • 定义了一个Set集合,用于存储正在创建的单例Bean的beanName
  • 对SingletonBeanRegistry接口提供方法的实现
package org.springframework.beans.factory.support;

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

    // 一级缓存
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	// 三级缓存
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	// 二级缓存
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

    // ...

    // 正在创建的单例Bean的beanName
	private final Set<String> singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));

    /**
     * 对registerSingleton方法的实现
     */
	@Override
	public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
        // ...
		synchronized (this.singletonObjects) {
            // 通过beanName先从一级缓存中获取
			Object oldObject = this.singletonObjects.get(beanName);
            // 一级缓存中已经有该beanName的对象,就抛异常
			if (oldObject != null) {
				throw new IllegalStateException("Could not register object [" + singletonObject +
						"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
			}
            // 一级缓存中没有该beanName的对象,就执行添加逻辑
			addSingleton(beanName, singletonObject);
		}
	}
    
    /**
     * 往容器中添加Bean
     */
	protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
            // beanName作为key,bean对象作为value,往一级缓存中添加
			this.singletonObjects.put(beanName, singletonObject);
            // 删除三级缓存中key为beanName的节点
			this.singletonFactories.remove(beanName);
            // 删除二级缓存中key为beanName的节点
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}

    // ...

    /**
     * 对getSingleton方法的实现(通过beanName获取bean对象)
     */    
	@Override
	@Nullable
	public Object getSingleton(String beanName) {
        // 调用重载方法
		return getSingleton(beanName, true);
	}

    /**
     * getSingleton第二个参数是boolean类型的重载方法
     */
	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        // 先从一级缓存中获取bean对象
		Object singletonObject = this.singletonObjects.get(beanName);
        // 一级缓存中没有该beanName对应的对象并且该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) {
                        // 执行三级缓存中的Lambda表达式的逻辑
						singletonObject = singletonFactory.getObject();
                        // 放入二级缓存
						this.earlySingletonObjects.put(beanName, singletonObject);
                        // 删除三级缓存中key为beanName的节点
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
        // 返回bean对象
		return singletonObject;
	}

    /**
     * getSingleton的重载方法
     * 第二个参数为Lambda表达式,为bean的创建过程
     */
	public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		// ...

		synchronized (this.singletonObjects) {
            // 先从一级缓存中获取bean对象
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
                // bean正在被创建,抛异常
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
                // ...

                // 创建bean之前,做一个标记,标记该beanName的bean正在创建中
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;

                // ...

				try {
                    // 执行Lambda的逻辑,执行bean的实例化和初始化流程
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
                    // ...
				}
				catch (BeanCreationException ex) {
                    // ...
				}
				finally {
                    // ...
                    
                    // 移除该beanName正在创建对象的标识
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
                    // 将完成实例化和初始化的bean对象放入单例池中
					addSingleton(beanName, singletonObject);
				}
			}
            // 返回bean对象
			return singletonObject;
		}
	}
}

Spring中处理循环引用的流程分析

定义两个具有循环引用特点的Bean

package spring.demo;

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

/**
 * A依赖B
 */
@Component
public class A {

    @Autowired
    private B b;
}
package spring.demo;

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

/**
 * B依赖A
 */
@Component
public class B {

    @Autowired
    private A a;
}

执行A的实例化

一、DefaultListableBeanFactory#preInstantiateSingletons

遍历beanNames,根据beanName实例化非懒加载的单例Bean

二、AbstractBeanFactory#getBean

getBean - doGetBean

三、AbstractBeanFactory#doGetBean

先尝试从容器中获取,有就直接返回

四、DefaultSingletonBeanRegistry#getSingleton

此时单例池singletonObjects中并没有beanName为a的对象,且并没有正在创建中,所以返回null

五、AbstractBeanFactory#doGetBean

调用getSingleton方法并传入beanName+Lambda表达式

六、DefaultSingletonBeanRegistry#getSingleton

  1. 此时singletonObjects中没有a
  2. 标记a正在创建中
  3. 执行传入的Lambda表达式,即createBean方法

七、AbstractAutowireCapableBeanFactory#createBean

createBean - doCreateBean

八、AbstractAutowireCapableBeanFactory#doCreateBean

  1. Bean的实例化
  2. 可以看到,Bean对象已经创建(A@2126)
  3. 添加到singletonFactories中(key为beanName,value为ObjectFactory)

九、AbstractAutowireCapableBeanFactory#getEarlyBeanReference

并非将已经实例化但未初始化的Bean对象直接放入singletonFactories(三级缓存)中,考虑到代理对象,所以放入的是Lambda表达式,也就是该方法的执行逻辑

十、DefaultSingletonBeanRegistry#addSingletonFactory

放入singletonFactories(三级缓存)中,key为beanName,value为一个Lambda表达式

执行A的属性填充(执行过程中发现A依赖B,就去执行B的实例化逻辑)

一、AbstractAutowireCapableBeanFactory#doCreateBean

填充Bean

二、AbstractAutowireCapableBeanFactory#populateBean

  1. @Autowired注解是通过AutowiredAnnotationBeanPostProcessor解析的
  2. 这里执行AutowiredAnnotationBeanPostProcessor的postProcessProperties方法

三、AutowiredAnnotationBeanPostProcessor#postProcessProperties

找到A中的b字段需要注入

四、InjectionMetadata#inject

调用AutowiredAnnotationBeanPostProcessor中的inject方法

五、AutowiredAnnotationBeanPostProcessor#inject

调用DefaultListableBeanFactory的resolveDependency方法

六、DefaultListableBeanFactory#resolveDependency

resolveDependency - doResolveDependency

七、DefaultListableBeanFactory#doResolveDependency

  1. autowiredBeanName:依赖的beanName
  2. instanceCandidate:依赖的bean类型

八、DependencyDescriptor#resolveCandidate

调用DefaultListableBeanFactory的getBean方法,此时beanName为b,也就是接下来要执行B的实例化、属性填充、初始化逻辑

执行B的实例化

一、AbstractBeanFactory#getBean

getBean - doGetBean

二、AbstractBeanFactory#doGetBean

此时容器中没有b对象,返回null

三、AbstractAutowireCapableBeanFactory#createBean

createBean - doCreateBean

四、AbstractAutowireCapableBeanFactory#doCreateBean

  1. Bean的实例化
  2. 实例化后的Bean对象和Bean的类型
  3. 将b和对应的Lambda表达式添加到三级缓存中
  4. 此时三级缓存中存在a,b两个元素
  5. 填充b对象属性

 

执行B的属性填充

一、AbstractAutowireCapableBeanFactory#populateBean

同样的,通过AutowiredAnnotationBeanPostProcessor的postProcessProperties方法中处理@Autowired注解

二、AutowiredAnnotationBeanPostProcessor#postProcessProperties

找到B依赖A

三、InjectionMetadata#inject

执行AutowiredAnnotationBeanPostProcessor的inject方法进行属性注入

四、AutowiredAnnotationBeanPostProcessor#inject

调用DefaultListableBeanFactory的resolveDependency方法

五、DefaultListableBeanFactory#resolveDependency

resolveDependency - doResolveDependency

六、DefaultListableBeanFactory#doResolveDependency

获取到注入的beanName和类型,调用DependencyDescriptor的resolveCandidate方法

七、DependencyDescriptor#resolveCandidate

从容器中获取a对象

八、AbstractBeanFactory#getBean

getBean - doGetBean

九、DefaultSingletonBeanRegistry#getSingleton

此时发生了改变

  1. 从singletonObjects(一级缓存)中获取a,没有
  2. beanName为a的Bean正在创建
  3. 从earlySingletonObjects(一级缓存)中获取a,同样没有
  4. 但是,从三级缓存singletonFactories中获取a,能获取到,此时执行三级缓存中a对应的Lambda表达式的逻辑
  5. 执行Lambda表达式后拿到a对象
  6. 将a对象(实例化了但未进行初始化)放入二级缓存中
  7. 删除三级缓存中的a

 

十、AutowiredAnnotationBeanPostProcessor#inject

通过反射将a对象赋值给b对象的a字段

执行B的初始化

一、AbstractAutowireCapableBeanFactory#doCreateBean

调用initializeBean执行b对象后续的初始化逻辑

二、AbstractAutowireCapableBeanFactory#initializeBean

  1. Aware接口方法的回调(BeanNameAware、BeanClassLoaderAware、BeanFactoryAware)
  2. BeanPostProcessor的初始化前方法回调
  3. InitializingBean的afterPropertiesSet方法回调和自定义的初始化方法回调
  4. BeanPostProcessor的初始化后方法回调
  5. 返回完成初始化的b对象

三、DefaultSingletonBeanRegistry#getSingleton

  1. 此时已经执行完b对应的Lambda表达式的doCreateBean的逻辑,拿到的是b已经实例化并初始化好的Bean对象
  2. 删除b正在创建的标识
  3. 将b添加到一级缓存singletonObjects单例池中,删除三级缓存和二级缓存中的b
  4. 返回已经实例化并初始化好的b对象

执行A的属性填充(此时依赖的B已经完成了实例化和初始化放到容器的单例池中,接着执行之前没有执行完成的A的属性填充逻辑)

一、AutowireAnnotationBeanPostProcessor#inject

通过反射将b对象赋值给a对象的b字段(b对象中的a字段此时的值为完成了实例化但未进行初始化的a对象,没有进行初始化的对象并不影响别的对象去引用,后续对a对象进行初始化即可)

执行A的初始化

一、AbstractAutowireCapableBeanFactory#doCreateBean

执行a对象的初始化逻辑

二、DefaultSingletonBeanRegistry#getSingleton

执行完a对象的初始化逻辑,将a添加到一级缓存singletonObjects中,删除三级缓存和二级缓存中的a,至此完成了相互引用的a和b对象的实例化和初始化逻辑,并将它们放入了容器的单例池中