Spring singleton Bean的生命周期

·  阅读 891

流程概览

singleton 作用域下的 Bean 整个创建过程要经历以下几个步骤

getBean(){
	doGetBean(){
		createBean(){
			doCreateBean(){}
		}
	}
}
复制代码

上面带层次的伪代码,只是帮助大家理解这几个重要方法对应的层次,其中 do 开头的才是真正干活的方法

singleton 作用域下, Bean 创建过程从 Ioc 容器的 getBean()方法开始,它会调用 doGetBean() 方法获取 Bean

而真正干活的方法 doGetBean() 方法,首先会从缓存中获取,如果获取不到就调用 createBean() 方法

同理 createBean() 方法也会调用 doCreateBean() 来进行真正的创建工作,之后doCreateBean() 会对 Bean 进行实例化 -> 属性赋值 -> 初始化,最后将创建好的 Bean 放入缓存中

流程总结

在整个流程中,我们只需要关心 doGetBean() 、doCreateBean() 两个“真正干活”的方法,这两个方法做的事情也很简单

  • doGetBean() : 从缓存中获取 Bean,没有就调用创建方法
  • doCreateBean() : 创建 Bean,并将其放入缓存中

虽然说的很简单,但其实这两个方法里面有大量精巧的设计,初次学习会有点难度,需要多学习几遍

三级缓存

上面提到 doGetBean() 方法首先会从缓存中获取 Bean,这个缓存就是常说的 Spring 三级缓存

它们其实就是三个 Map ,位于 DefaultSingletonBeanRegistry 类下

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
	// 第一级缓存,缓存 初始化 完的 bean
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
	
	// 第二级缓存,缓存 实例化 完的 bean
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
        
	// 第三级缓存,缓存 bean Factory
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	// 记录已创建过的 Bean
	private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

	// 记录正在创建中的 Bean
	private final Set<String> singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));
}
复制代码

各级缓存的作用:

  • 第一级缓存 singletonObjects :缓存 初始化 完的 bean ,实现 Beansingleton 作用域,即 Bean 的单例模式
  • 第二级缓存 earlySingletonObjects :缓存 “bean 的提前引用(Bean 或 Bean 的代理对象)” ,解决循环依赖
  • 第三级缓存 singletonFactories :缓存获取 “bean 的提前引用” 的工厂,推迟 Bean 或 Bean 的代理对象的获取时机

doGetBean() 方法

AbstractBeanFactory.doGetBean() 方法是真正获取 Bean 的核心方法,它里面做的事情非常多,这里只关注最最最重要的2处代码

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
 
	// 1.根据 beanName 尝试从缓存中获取 Bean,如果缓存中有,则直接return,如果缓存中没有,且Bean不在创建中则返回null
	Object beanInstance = getSingleton(beanName);
	...
	
        if (!typeCheckOnly) {
            //标记名称为 {beanName} 的 Bean 正在创建中
            markBeanAsCreated(beanName);
	}

	// 2.创建 Bean。 虽然方法名称也叫 getSingleton ,但是它传入了一个可以创建 Bean 的匿名函数,它会在内部调用该匿名函数,进行 Bean 的“创建”
	sharedInstance = getSingleton(beanName, () -> { return createBean(beanName, mbd, args); });
    }
}
复制代码

极简版如下

doGetBean(){
    //1. 获取 Bean
    getSingleton(beanName);
    //2. “创建” Bean
    getSingleton(beanName, () -> { return createBean(beanName, mbd, args); });
}
复制代码

这两个 getSingleton() 方法都位于 DefaultSingletonBeanRegistry 类下,一个一个来看

getSingleton(beanName)

首先来看 getSingleton(beanName); 方法,它其实是调用了 getSingleton(beanName, true); 方法

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    
    public Object getSingleton(String beanName) {
       return getSingleton(beanName, true);
    }

    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
       // 从第一级缓存 singletonObjects 中取
       Object singletonObject = this.singletonObjects.get(beanName);
       if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
          synchronized (this.singletonObjects) {
             // 没取到,从第二级缓存 earlySingletonObjects 中取 
             singletonObject = this.earlySingletonObjects.get(beanName);
             if (singletonObject == null && allowEarlyReference) {
                // 还没取到,从第三级缓存 singletonFactories 中取出该 bean 的工厂对象
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                   // 通过工厂对象生产该 bean 的实例,注意这里拿到的可能是一个 bean 的代理对象
                   singletonObject = singletonFactory.getObject();
                   // 然后添加到第二级缓存 earlySingletonObjects 中
                   this.earlySingletonObjects.put(beanName, singletonObject);
                   // 最后删除掉第三级缓存 singletonFactories 中该 bean 的工厂
                   this.singletonFactories.remove(beanName);
                }
             }
          }
       }
       return singletonObject;
    }
}
复制代码

极简版如下

getSingleton() {
    // 1 从第一级缓存 singletonObjects 中取
	singletonObject = this.singletonObjects.get(beanName);
	// 2 没取到,从第二级缓存 earlySingletonObjects 中取 
	singletonObject = this.earlySingletonObjects.get(beanName);
    if (allowEarlyReference) {
        // 3-1 还没取到,从第三级缓存 singletonFactories 中取出该 bean 的工厂对象
        ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
        // 3-2 通过工厂对象生产该 bean 的实例,注意这里拿到的可能是一个 bean 的代理对象
        singletonObject = singletonFactory.getObject();
        // 3-3然后添加到第二级缓存 earlySingletonObjects 中
        this.earlySingletonObjects.put(beanName, singletonObject);
        // 3-4最后删除掉第三级缓存 singletonFactories 中该 bean 的工厂
        this.singletonFactories.remove(beanName);
    }
    return singletonObject;
}
复制代码

getSingleton(beanName, ObjectFactory<?>)

这就是上面 doGetBean() 中调用“创建” Bean 的方法

//2. “创建” Bean
getSingleton(beanName, () -> { return createBean(beanName, mbd, args); });
复制代码

这个方法中做的事情也非常多,我们只看最最最重要的几块

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    // 创建前的处理
    beforeSingletonCreation(beanName);
    //1.创建 bean。singletonFactory 对象,就是上面那段的匿名函数,getObject()方法对应的就是匿名函数的具体实现
    singletonObject = singletonFactory.getObject();
    // 创建后的处理
    afterSingletonCreation(beanName);
    // 2.将 bean 添加到缓存中
    addSingleton(beanName, singletonObject);
    return singletonObject;
}
复制代码

极简版如下

getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    //1.创建 bean。相当于 singletonObject = createBean(beanName, mbd, args);
    singletonObject = singletonFactory.getObject();
    // 2.将 bean 添加到缓存中
    addSingleton(beanName, singletonObject);
}
复制代码

这里面又有两个重要的方法

  • createBean(beanName, mbd, args) : 这个就是文章开头提到的 createBean() 方法

  • addSingleton(beanName, singletonObject) : 添加 Bean 到第一级缓存中

我们先看 addSingleton(beanName, singletonObject) 方法

addSingleton()

这个方法同样位于 DefaultSingletonBeanRegistry 类下,而且源码非常简单,如下

protected void addSingleton(String beanName, Object singletonObject) {
   synchronized (this.singletonObjects) {
   	  // 将 Bean 添加到第一级缓存中	
      this.singletonObjects.put(beanName, singletonObject);
      // 将 Bean 从第三级缓存中删除
      this.singletonFactories.remove(beanName);
      // 将 Bean 从第二级缓存中删除
      this.earlySingletonObjects.remove(beanName);
      // 标记 {beanName} 对应的 Bean 已创建
      this.registeredSingletons.add(beanName);
   }
}
复制代码

this.registeredSingletonsDefaultSingletonBeanRegistry 类的一个属性

private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
复制代码

代表着已创建过的 Bean

doGetBean() 方法总结

以下极简版的 doGetBean() 整个流程,最重要的是在第二次 getSingleton() 时,传入了一个 ObjectFactory的实现类,实现了 创建 Bean 的方法,之后在方法内部会调用该方法,进入到创建 bean 的阶段

doGetBean(){
	getSingleton(beanName);
	getSingleton(beanName, () -> { return createBean(beanName, mbd, args); });
}

getSingleton(beanName){
    // 1 从第一级缓存 singletonObjects 中取
    singletonObject = this.singletonObjects.get(beanName);
    // 2 没取到,从第二级缓存 earlySingletonObjects 中取 
    singletonObject = this.earlySingletonObjects.get(beanName);
    if (allowEarlyReference) {
        // 3-1 还没取到,从第三级缓存 singletonFactories 中取出该 bean 的工厂对象
        ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
        // 3-2 通过工厂对象生产该 bean 的实例
        singletonObject = singletonFactory.getObject();
        // 3-3然后添加到第二级缓存 earlySingletonObjects 中
        this.earlySingletonObjects.put(beanName, singletonObject);
        // 3-4最后删除掉第三级缓存 singletonFactories 中该 bean 的工厂
        this.singletonFactories.remove(beanName);
    }
}

getSingleton(beanName, beanFactory){
    // 1.创建 bean。相当于 singletonObject = createBean(beanName, mbd, args);
    singletonObject = singletonFactory.getObject();
    // 2.将 bean 添加到缓存中
    addSingleton(beanName, singletonObject);
}

addSingleton(beanName, singletonObject){
    // 将 Bean 添加到第一级缓存中	
    this.singletonObjects.put(beanName, singletonObject);
    // 将 Bean 从第三级缓存中删除
    this.singletonFactories.remove(beanName);
    // 将 Bean 从第二级缓存中删除
    this.earlySingletonObjects.remove(beanName);
    // 标记 {beanName} 对应的 Bean 已创建
    this.registeredSingletons.add(beanName);
}
复制代码

createBean(beanName, mbd, args)

上面说到,doGetBean() 获取不到对象,会来调用 createBean(beanName, mbd, args),我们来看下 createBean() 方法中做了什么事情,如下只保留了最最最核心的代码

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {

	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {
            // 拿到 Bean 的 Definition 对象
            Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
            if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
                mbdToUse = new RootBeanDefinition(mbd);
                mbdToUse.setBeanClass(resolvedClass);
            }

            // 调用 doCreateBean() 方法
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
	}
}
复制代码

这里面最重要的还是 doCreateBean() 方法,我们直接看该方法

doCreateBean() 方法

doCreateBean() 方法位于 AbstractAutowireCapableBeanFactory 类下,这个方法的内容也非常多,我们只看最最最重要的

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
	    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
        // 1.实例化 Bean,并从返回的 BeanWrapper 包装类中取出 bean 对象。注意此时 bean 还是原始对象
        instanceWrapper = createBeanInstance(beanName, mbd, args);
        final Object bean = instanceWrapper.getWrappedInstance();

        // 是否”提前暴露“原始对象的引用,用于解决循环依赖。对于单例Bean,该变量一般为 true
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            //2.往第三级缓存中添加一个 ObjectFactory 接口的实现类,就是下面这个匿名函数,调用该匿名函数可以获得一个 bean 对象或者 bean 的代理对象,实现 AOP
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // 3.填充属性(依赖注入)
        populateBean(beanName, mbd, instanceWrapper);
        // 4. Bean初始化
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
}
复制代码

极简版

doCreateBean(){
	// 1.实例化 Bean
	createBeanInstance(beanName, mbd, args);
        
	//2.往第三级缓存中添加一个 ObjectFactory 接口的实现类,就是下面这个匿名函数,调用该匿名函数可以获得一个 bean 对象或者 bean 的代理对象
	addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
     
	// 3.填充属性(依赖注入)
	populateBean(beanName, mbd, instanceWrapper);
	
	// 4. Bean初始化
	initializeBean(beanName, exposedObject, mbd);
}
复制代码

这上面的每一个方法都非常重要,我们先看 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); 这句代码

getEarlyBeanReference()

这个方法很有意思,名称叫做 获取 bean 的提前引用,什么叫“提前引用” 这是为了解决循环依赖提出来的,可以理解为一个已经实例化但还没有填充属性的对象

关于循环依赖这块,参考 Spring 循环依赖

getEarlyBeanReference() 方法源码如下

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;
}
复制代码

虽说方法名称叫做获取 bean 的提前引用,但是你看入参,已经传入了一个 bean 对象,结合 doCreateBean() 方法中的代码

//实例化 Bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
final Object bean = instanceWrapper.getWrappedInstance();
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
复制代码

这里传进去的 bean 就是一个 "提前引用"(已经实例化但还没有填充属性的对象)

你可能有疑问了,既然已经有了 "提前引用" 那还有必要调用 getEarlyBeanReference(beanName, mbd, bean) 再次获取 bean 的提前引用吗?

其实 getEarlyBeanReference(beanName, mbd, bean) 方法真正的作用是,如果传入的 bean 被代理,则返回代理对象,否则原样返回,核心代码就下面一句

// AbstractAutoProxyCreator 会继承 SmartInstantiationAwareBeanPostProcessor 并重写 getEarlyBeanReference 方法,返回一个代理对象
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
复制代码

ibp 是 SmartInstantiationAwareBeanPostProcessor 类型,getEarlyBeanReference(exposedObject, beanName) 方法用于返回一个 "提前引用" ,默认实现是将 bean 原样返回,但如果我们使用 Spring AOP 对该 Bean 进行了代理,那么 ibp 可能对应SmartInstantiationAwareBeanPostProcessor 的子类,比如 AbstractAutoProxyCreator ,它继承了 SmartInstantiationAwareBeanPostProcessor 并重写了 getEarlyBeanReference(); 方法,返回了一个代理对象

addSingletonFactory()

addSingletonFactory() 同样位于 DefaultSingletonBeanRegistry 类下,方法也很简单,源码如下:

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
   Assert.notNull(singletonFactory, "Singleton factory must not be null");
   synchronized (this.singletonObjects) {
      // 如果 bean 不在第一级缓存中
      if (!this.singletonObjects.containsKey(beanName)) {
         // 将 ObjectFactory 接口的实现类,就是上一节中的匿名函数添加到第三级缓存中
         this.singletonFactories.put(beanName, singletonFactory);
         // 将 bean 从删除第二级缓存中删除
         this.earlySingletonObjects.remove(beanName);
         // 将该 bean 标记为已注册
         this.registeredSingletons.add(beanName);
      }
   }
}
复制代码

有了上面的了解,我们再回头来看 doGet() 中的这段代码

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
复制代码

将一个匿名函数添加到了第三级缓存中,而这个匿名函数可能会获得一个 bean 的代理对象

还记得这个第三级缓存什么时候被用到吗?在 doGetBean() 的时候,我们用来了 getSingleton(beanName); 方法,它里面会去使用第三级缓存,让我们重新回顾一下 getSingleton() 方法

getSingleton() {
    // 1 从第一级缓存 singletonObjects 中取
	singletonObject = this.singletonObjects.get(beanName);
	// 2 没取到,从第二级缓存 earlySingletonObjects 中取 
	singletonObject = this.earlySingletonObjects.get(beanName);
    if (allowEarlyReference) {
        // 3-1 还没取到,从第三级缓存 singletonFactories 中取出该 bean 的工厂对象
        ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
        // 3-2 通过工厂对象生产该 bean 的实例
        singletonObject = singletonFactory.getObject();
        // 3-3然后添加到第二级缓存 earlySingletonObjects 中
        this.earlySingletonObjects.put(beanName, singletonObject);
        // 3-4最后删除掉第三级缓存 singletonFactories 中该 bean 的工厂
        this.singletonFactories.remove(beanName);
    }
    return singletonObject;
}
复制代码

上面 3-1 中 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); 得到的 singletonFactory 就是上面 doCreateBean() 中设置进去的匿名函数

3-2 中 singletonFactory 调用 getObject(); 方法,就是执行匿名函数中的 getEarlyBeanReference(beanName, mbd, bean) 方法,所以,3-2 中返回的 singletonObject 对象,可能是一个代理对象

3-3 中把 singletonObject 对象(可能是一个代理对象),放入了二级缓存,之后在 3-4 中,移除了匿名函数

addSingletonFactory() 的设计思想

回头来看这段代码

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

为什么不这样写

// 获取到 bean 的“提前引用”,这个 “提前引用” 可能是一个代理对象
Object EarlyBean = getEarlyBeanReference(beanName, mbd, bean);
// 跳过第三级缓存,直接添加到第二级缓存中
addEarlySingleton(beanName, EarlyBean);
复制代码

我是这样理解的,addSingletonFactory() 这样设计的目的是推迟 bean "提前引用" 的获取时机,只有 getSingleton() 时,才会真正获取 bean 的"提前引用"

populateBean()

doCreateBean() 中的 populateBean() 方法同样位于 AbstractAutowireCapableBeanFactory 类下,用于给实例化完的 bean 填充属性(注入依赖),我们只看最最最重要的三块代码

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    // 1.基于 byName 的自动装配
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
       autowireByName(beanName, mbd, bw, newPvs);
    }

    // 2.基于 byType 的自动装配
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
       autowireByType(beanName, mbd, bw, newPvs);
    }
    
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            // 3.填充属性
            pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
            if (pvs == null) {
                return;
            }
        }
    }
}
复制代码

上面的1、2、3 三种方式都可以给 bean 填充属性,具体使用哪一中方法给 bean 填充属性,要看 mbd.getResolvedAutowireMode() 的返回结果

getResolvedAutowireMode() 源码如下

public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor implements BeanDefinition, Cloneable {
    // 不自动装配
    public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;

    // 根据 bean 的名称进行自动装配
	public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;

    // 根据 bean 的类型进行自动装配
	public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;

    // 根据构造方法进行自动装配
	public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;

	// 自动检测
    @Deprecated
	public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
    
    // 默认不自动装配
    private int autowireMode = AUTOWIRE_NO;
    
	public int getResolvedAutowireMode() {
		if (this.autowireMode == AUTOWIRE_AUTODETECT) {
			Constructor<?>[] constructors = getBeanClass().getConstructors();
			for (Constructor<?> constructor : constructors) {
				if (constructor.getParameterCount() == 0) {
					return AUTOWIRE_BY_TYPE;
				}
			}
			return AUTOWIRE_CONSTRUCTOR;
		}
		else {
			return this.autowireMode;
		}
	}
}
复制代码

如果没有显式配置自动装配策略,例如如在 XML 配置文件中显式指定了 autowired 或者在 Java 配置类中 @Bean 上,声明 autowired

<bean id="a" class="com.wqlm.Test.A" autowire="byName">
    <property name="b" value="1" />
</bean> 
@Bean(autowire = Autowire.BY_NAME)
复制代码

那么autowireMode 为默认值, autowireMode = AUTOWIRE_NO ,不走 1、2 分支的,而是执行3 中的代码,我们平常使用@Resource@Autowired 注解来进行字段或者 setter() 注入都是执行3 中的代码

我们仔细来分析一下3 中的代码

// 拿到当前所有实现了 BeanPostProcessor 接口的实现类,并遍历
for (BeanPostProcessor bp : getBeanPostProcessors()) {
	// InstantiationAwareBeanPostProcessor 是 BeanPostProcessor 的子接口
    if (bp instanceof InstantiationAwareBeanPostProcessor) {
        // 类型转换
        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
        // 3.填充属性
        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
        if (pvs == null) {
            return;
        }
    }
}
复制代码

其实就是调用所有 InstantiationAwareBeanPostProcessor 接口的实现类的 postProcessPropertyValues()方法

该接口的实现类特别多,这里只需要关注AutowiredAnnotationBeanPostProcessor,从名字中就可以看出,它是对基于注解(@Resource@Autowired)的自动装配进行 BeanPostProcessor

image.png

当我们使用注解(@Resource@Autowired)的方式进行依赖注入时,在 populateBean() 中会调用 AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues() 方法

image.png

而从堆栈中我们可以看到,它最终会去调用 doGetBean() 去获取/创建依赖 bean,之后通过反射或 setter() 方法,将获取到的 bean 填充到属性中

这就是属性填充的基本流程,用伪代码表示就是

populateBean(){
	AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(){}
}

postProcessPropertyValues(){
	// 获取依赖对象
	Object o = doGetBean();
	// 设置依赖
	bean.setxxx(o);
}
复制代码

initializeBean()

populateBean() 方法执行完成之后,Bean 中的依赖就都填充好了,而 initializeBean() 方法是进一步对 Bean 进行扩展和增强,如果我们的 Bean 实现了以下这些接口,那么会按照顺序依次调用对应的方法

image.png

doCreateBean() 方法总结

以下极简版的 doCreateBean() 整个流程

doCreateBean(){
	// 1.实例化 Bean
	createBeanInstance(beanName, mbd, args);
        
	//2.往第三级缓存中添加一个 ObjectFactory 接口的实现类,就是下面这个匿名函数,调用该匿名函数可以获得一个 bean 对象或者 bean 的代理对象
	addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
     
	// 3.填充属性(依赖注入)
	populateBean(beanName, mbd, instanceWrapper);
	
	// 4. Bean初始化
	initializeBean(beanName, exposedObject, mbd);
}

//2
addSingletonFactory(beanName, singletonFactory) {
    // 如果 bean 不在第一级缓存中
    if (!this.singletonObjects.containsKey(beanName)) {
        // 将 ObjectFactory 接口的实现类,就是上面的匿名函数添加到第三级缓存中
        this.singletonFactories.put(beanName, singletonFactory);
        // 将 bean 从删除第二级缓存中删除
        this.earlySingletonObjects.remove(beanName);
        // 将该 bean 标记为已注册
        this.registeredSingletons.add(beanName);
    }
}

// 3 伪代码
populateBean(beanName, mbd, instanceWrapper){
	// 获取依赖对象
	Object o = doGetBean();
	// 设置依赖
	bean.setxxx(o);
}
复制代码

上面最重要的是实例化后,调用 addSingletonFactory() 方法在第三级缓存中放入了一个可以拿到 bean 代理对象ObjectFactory 。以及填充属性时,通过 doGetBean() 在缓存中获取依赖

总结

整个生命周期用代码表示如下

doGetBean(){
    //1. 从第一二三级缓存中依次获取 Bean
    getSingleton(beanName);
    //2. 获取不到,调用 createBean()  方法“创建” Bean
    getSingleton(beanName, () -> { return createBean(beanName, mbd, args); });
}

doCreateBean(){
	// 1.实例化 Bean
	createBeanInstance(beanName, mbd, args);
        
	//2.往第三级缓存中添加一个 ObjectFactory 接口的实现类,就是下面这个匿名函数,调用该匿名函数可以获得一个 bean 对象或者 bean 的代理对象
	addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
     
	// 3.填充属性(依赖注入),调用上面 doGetBean()方法获取依赖bean 并填充到属性
	populateBean(beanName, mbd, instanceWrapper);
	
	// 4. Bean初始化
	initializeBean(beanName, exposedObject, mbd);
}
复制代码

上面的伪代码,就是 singleton Bean 的生命周期中,最最最核心的流程,它解释了 Bean AOP 的时机,三级缓存的作用,以及 Spring 如何解决循环依赖

Spring 如何解决循环依赖

让我们用一个循环依赖的例子来巩固整个流程

参考 Spring bean 循环依赖

分类:
后端
标签:
收藏成功!
已添加到「」, 点击更改