(Spring)Bean生命周期(二)--- 获取单例Bean源码

上文说到了扫包最终得到了一个BeanDefinition的Map(Map<String, BeanDefinition> beanDefinitionMap),这章说获取单例Bean的步骤和源码,也就是Bean生命周期的后续步骤。

DefaultListableBeanFactory#preInstantiateSingletons() 获取单例Bean

public void preInstantiateSingletons() throws BeansException {
  if (logger.isTraceEnabled()) {
     logger.trace("Pre-instantiating singletons in " + this);
  }

  // Iterate over a copy to allow for init methods which in turn register new bean definitions.
  // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
  List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

  // Trigger initialization of all non-lazy singleton beans...
  for (String beanName : beanNames) {
     // 获取合并后的BeanDefinition
     RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

     if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
        if (isFactoryBean(beanName)) {
           // 获取FactoryBean对象
           Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
           if (bean instanceof FactoryBean) {
              FactoryBean<?> factory = (FactoryBean<?>) bean;
              boolean isEagerInit;
              if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                 isEagerInit = AccessController.doPrivileged(
                       (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
                       getAccessControlContext());
              }
              else {
                 isEagerInit = (factory instanceof SmartFactoryBean &&
                       ((SmartFactoryBean<?>) factory).isEagerInit());
              }
              if (isEagerInit) {
                 // 创建真正的Bean对象(getObject()返回的对象)
                 getBean(beanName);
              }
           }
        }
        else {
           // 创建Bean对象
           getBean(beanName);
        }
     }
  }

  // 所有的非懒加载单例Bean都创建完了后
  // Trigger post-initialization callback for all applicable beans...
  for (String beanName : beanNames) {
     Object singletonInstance = getSingleton(beanName);
     if (singletonInstance instanceof SmartInitializingSingleton) {
        StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
              .tag("beanName", beanName);
        SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
        if (System.getSecurityManager() != null) {
           AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
              smartSingleton.afterSingletonsInstantiated();
              return null;
           }, getAccessControlContext());
        }
        else {
           smartSingleton.afterSingletonsInstantiated();
        }
        smartInitialize.end();
     }
  }
}

以上是获取单例Bean的源码我们一步一步剖析其中的核心步骤

合并BeanDefinition

RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

在扫描得到BeanDefinition后就可以根据BeanDefinition来创建对象了,但是在Spring存在一种父子关系的Bean

<bean id = "parent" class="com.maxiake.service.Parent" scope = "prototype"/>
<bean id = "child" class="com.maxiake.service.Child"/>

这种在实际使用中呢比较少,上面的Child类的父亲是Parent 所以要继承他的scope属性那么就需要一个父子合并得到一个RootBeanDefinition

加载类

在加载类之前会根据刚刚合并得到的RootBeanDefinition来判断是否是一个接口Bean,是否单例,是否非懒加载,
校验通过呢又回去判断是否实现了FactoryBean接口

if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
   if (isFactoryBean(beanName)) {
      // 获取FactoryBean对象
      Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
      if (bean instanceof FactoryBean) {
         FactoryBean<?> factory = (FactoryBean<?>) bean;
         boolean isEagerInit;
         if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
            isEagerInit = AccessController.doPrivileged(
                  (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
                  getAccessControlContext());
         }
         else {
            isEagerInit = (factory instanceof SmartFactoryBean &&
                  ((SmartFactoryBean<?>) factory).isEagerInit());
         }
         if (isEagerInit) {
            // 创建真正的Bean对象(getObject()返回的对象)
            getBean(beanName);
         }
      }
   }
   else {
      // 创建Bean对象
      getBean(beanName);
   }
}

先来说一下什么是FactoryBean

FactoryBean

我们举一个简单的例子来说明

@Component
public class MaxiaKeService implements FactoryBean {
   
   
   @Override
   public Object getObject() throws Exception {
      return new UserService();
   }

   @Override
   public Class<?> getObjectType() {
      return UserService.class;
   }
   
}

MaxiaKeService实现了FactoryBean重写了他的两个方法

  • T getObejct(): 返回由FactoryBean创建的bean实例,如果isSingleton()返回true,则该实例会放到Spring容器中实例缓存池中。

  • Class<T> getObjectType(): 返回FactoryBean创建的 bean的类型。

FactoryBean还有一个方法有默认实现

  • boolean isSingleton():返回有FactoryBean创建的bean的实例的作用域是singleton还是prototype,这里默认返回的是true,也就是默认是singleton bean。

上述代码往Spring容器注入的是MaxiaKeService,当根据BeanName maxiaKeService来找Bean的时候将会得到UserService类型,用&maxiaKeService才能得到MaxiaKeService这个类,看上面源码也能发现在BeanDefinition实现FactoryBaen的时候会走两次getBean 也就是会进行两次Bean的实例化。

加载类

BeanDefinition合并后就可以去创建Bean对象了,而创建Bean就必须实例化对象,实例化就要先加载当前BeanDefinition所对应的class,在AbstractAutowireCapableBeanFactory#createBean()方法中,调用了:

Class<?> resolvedClass = resolveBeanClass(mbd, beanName);

这行代码就是去加载类,具体实现:

// 如果beanClass被加载了
if (mbd.hasBeanClass()) {
   return mbd.getBeanClass();
}

// 如果beanClass没有被加载
if (System.getSecurityManager() != null) {
   return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>)
         () -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
}
else {
   return doResolveBeanClass(mbd, typesToMatch);
}

如果beanClass属性是Class那么就直接返回,如果不是则会根据类名进行加载(doResolveBeanClass)

实例化前

加载到类就要执行实例化前的步骤了:

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

Spring提供了一个拓展点,允许开发者来控制实例化对象之前的一些操作,这个拓展点叫: InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()
实现这个接口后重写postProcessBeforeInstantiation()方法的话spring就会在实例化前去执行这个重写的逻辑处理。

推断构造方法

Spring在根据某个类创建Bean的过程中,需要使用构造方法来实例化得到一个对象,但是如果存在多个构造方法spring如何选择?
判断逻辑:
1.如果一个类只有一个构造方法不管是有参无参,spring都会选择该构造方法。
2.如果一个类有多个构造方法,spring会选取无参构造,如果不存在无参构造就会报错。
3.如果在构造方法上加上@Autowired注解,spring就会去选取这个构造去实例化。

实例化

AbstractAutowireCapableBeanFactory#doCreateBean()

// 创建Bean实例
instanceWrapper = createBeanInstance(beanName, mbd, args);

Supplier实例化对象

首先要判断BeanDefinition是否设置了Supplier设置了则使用Supplier来创建对象

Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
   return obtainFromSupplier(instanceSupplier, beanName);
}

工厂方法创建对象

如果没有Supplier,则检查是否设置了factoryMethod,也就是工厂方法

if (mbd.getFactoryMethodName() != null) {
   return instantiateUsingFactoryMethod(beanName, mbd, args);
}

BeanDefinition后置处理器

在实例化Bean出来后spring又提供了一个拓展点可以对BeanDefinition进行加工处理

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
   for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {
      processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
   }
}

这个拓展点由MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition()提供

实例化后

在处理完BeanDefinition后,Spring又设计了一个扩展点:

if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
   for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
      if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
         return;
      }
   }
}

InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()

属性赋值

populateBean(beanName, mbd, instanceWrapper);

这个步骤中,就会处理@Autowired、@Resource、@Value等注解

执行Aware

完成了属性赋值之后,Spring会执行一些回调,包括:

  1. BeanNameAware:回传beanName给bean对象。
  2. BeanClassLoaderAware:回传classLoader给bean对象。
  3. BeanFactoryAware:回传beanFactory给对象。

初始化前

 applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);

BeanPostProcessor.postProcessBeforeInitialization()这个拓展点实现
利用初始化前,可以对进行了依赖注入的Bean进行处理。

初始化

invokeInitMethods(beanName, wrappedBean, mbd);
  1. 查看当前Bean对象是否实现了InitializingBean接口,如果实现了就调用其afterPropertiesSet() 方法
  2. 执行BeanDefinition中指定的初始化方法

初始化后

applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

BeanPostProcessor.postProcessAfterInitialization()这个拓展点实现
以在这个步骤中,对Bean最终进行处理,Spring中的AOP就是基于初始化后实现的,初始化后返 回的对象才是最终的Bean对象。

总结BeanPostProcesso

  1. InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
  2. 实例化
  3. MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()
  4. InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
  5. 自动注入
  6. InstantiationAwareBeanPostProcessor.postProcessProperties()
  7. Aware对象
  8. BeanPostProcessor.postProcessBeforeInitialization()
  9. 初始化
  10. BeanPostProcessor.postProcessAfterInitialization()

猜你喜欢

转载自juejin.im/post/7115311335449034782