spring系列14:实例化Bean

前言

registerBeanPostProcessors 之后,Spring 要开始准备实例化 Bean。不过在这之前,Spring 初始化了非常多的内部组件。

// 国际化消息组件
initMessageSource();

// Initialize event multicaster for this context.
// 初始化事件监听多路广播器
initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.
// 没有具体实现
onRefresh();

// Check for listener beans and register them.
// 注册监听器
registerListeners();

// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

这些组件目前不需要话费太大精力去研究,不过要注意一点是在实例化 Bean 前,Spring 留了个扩展方法onRefresh();给程序员扩展。

finishBeanFactoryInitialization

走到这里,要进入 Spring 的核心。

这个方法技术点过于庞大,Spring 对各个执行步骤都考虑的非常周全,因此这个方法内部看起来非常的复杂,往往看到一个点,需要往后面深入好几层,返回来才明白 Spring 开发者为什么这么做。

所以,对于此方法,需要拆分为好几步去分析。这次只需要知道如何实例化一个普通 bean

配置一个类

以注解配置的方式配置一个 Bean

Myconfig.java

@Configurable
@ComponentScan("com.Playwi0.bean")
public class MyConfig {

}

A.java

javapackage com.Playwi0.bean;

import org.springframework.stereotype.Component;

@Component
public class A {


   public A(){
      System.out.println("a");
   }
}

就这么个普通的 Bean,来看看 Spring 如何实例化。为了简洁明了,我会删去与本次主体无关代码

preInstantiateSingletons

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {

    // 删去代码
    ...... 

   // Instantiate all remaining (non-lazy-init) singletons.
   // 开始实例化 bean
   beanFactory.preInstantiateSingletons();
}

跟进此方法 preInstantiateSingletons

@Override
public void preInstantiateSingletons() throws BeansException {

    // 删去代码
    .....
   // 先 copy 一份所有添加到 BeanFactory 的 beanDefinition 的名称
   List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

   for (String beanName : beanNames) {

      // 通过 getMergedLocalBeanDefinition 方法合并所有需要合并的 BeanDefinition
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

      // 要在这一步初始化需要满足三个条件:不是抽象类,BeanDefinition 必须是单例,没有设置延迟加载
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {

         if (isFactoryBean(beanName)) {

            // 删去代码
            .....
         }
         else {
            getBean(beanName);
         }
      }
   }

    // 删去代码
    .....

}

遍历所有的 beanDefinition 的名称,调用了getMergedLocalBeanDefinition(beanName);方法进行 BeanDefinition 之间的合并,这个方法后面文章会细讲,这里只需要知道当前 BeanDefinition 会与父类或接口的 BeanDefinition 某些属性进行整合,得到全新的 RootBeanDefinition

要想实例化 Bean,还要满足三个要求:不是抽象类,BeanDefinition 必须是单例,没有设置延迟加载。也就是在 Spring 开始的时候,原型类型的 Bean,并不会实例化。

最后判断是不是 FactoryBean,前面配置的肯定不是一个 FactoryBean,因此会进入getBean(beanName);.

getBean

getBean 也是一个非常重要的方法,同样的,在这里我们只需截取需要的部分就可以,后面还会具体分析。

@Override
public Object getBean(String name) throws BeansException {
   return doGetBean(name, null, null, false);
}

这里面调用的是 doGetBean 方法

doGetBean

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
      @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

   // 删除代码
   ....

   // 从缓存找 Bean,如果已经实例化可以找到
   Object sharedInstance = getSingleton(beanName);

   if (sharedInstance != null && args == null) {

       // 删除代码
        ....

   }

   else {


      // 删除代码
      ....

      // 如果没有实例化 BeanDefinition 则递归循环调用父 BeanFactory,也就是最顶层的 BeanFactory 去实例化 BeanDefinition
      BeanFactory parentBeanFactory = getParentBeanFactory();
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
         // Not found -> check parent.
         String nameToLookup = originalBeanName(name);
         if (parentBeanFactory instanceof AbstractBeanFactory) {
            return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                  nameToLookup, requiredType, args, typeCheckOnly);
         }
         else if (args != null) {
            // Delegation to parent with explicit args.
            return (T) parentBeanFactory.getBean(nameToLookup, args);
         }
         else if (requiredType != null) {
            // No args -> delegate to standard getBean method.
            return parentBeanFactory.getBean(nameToLookup, requiredType);
         }
         else {
            return (T) parentBeanFactory.getBean(nameToLookup);
         }
      }

      // 删除代码
      ....

      try {

         final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

         // 不是抽象类
         checkMergedBeanDefinition(mbd, beanName, args);


         // 如果有 DependsOn,要先实例化 DependsOn 的 Bean
         String[] dependsOn = mbd.getDependsOn();
         if (dependsOn != null) {

            // 删除代码
            ....

         }

         // Create bean instance.
         if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName, () -> {
               try {
                  return createBean(beanName, mbd, args);
               }
               catch (BeansException ex) {

                  destroySingleton(beanName);
                  throw ex;
               }
            });

            // 删除代码
            ....

         }

         else if (mbd.isPrototype()) {

            // 删除代码
            ....
         }
   return (T) bean;
}

Spring 在实例化之前,会检查一遍缓存,如果已经实例化,会从缓存里取出来。

Object sharedInstance = getSingleton(beanName);

我们是第一次进来,正常情况下是没有实例化的,因此会到else逻辑。

这里的第一步是递归找出父 BeanFactory,有点类似于 Java 的双亲委派机制,采用最顶层的 BeanFactory 去生产 Bean,防止多次加载。正常情况是不会经过这里。

最终走进try 代码块,第一步和前面一样合并 BeanDefinition,再一次检查是不是抽象类,抽象类是不能实例化的。

protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args)
      throws BeanDefinitionStoreException {

   if (mbd.isAbstract()) {
      throw new BeanIsAbstractException(beanName);
   }
}

可能你会问,这里为什么只判断一个条件?注意这里是 getBean 方法进来,这个方法外面也是可以调用的,而前面三个条件,是 Spring 初始化内部的判断。

在这之后,如果该类有依赖的 Bean,要先实例化依赖的 Bean 调用的也是 getBean 方法。很明显前面配置的 Bean 是没有的。

再一次判断是否为单例,单例有单例的实例化方式,原型有原型的。前面并没有配置,默认为单例,进入到 getSingleton 方法,这个方法和上面的并不是同一个方法,同时里面传了个 Lamber 表达式,转换一下,更好阅读一点

public interface ObjectFactory<T> {

    T getObject() throws BeansException;

}


ObjectFactory singletonFactory = new ObjectFactory{

    public T getObject() throws BeansException{
        return createBean(beanName, mbd, args);
    }
}

sharedInstance = getSingleton(beanName,  singletonFactory);

getSingleton

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
   Assert.notNull(beanName, "Bean name must not be null");
   synchronized (this.singletonObjects) {

      Object singletonObject = this.singletonObjects.get(beanName);

      if (singletonObject == null) {
         // 删除代码
         ....

         // 把 Bean 加入到正在创建集合 this.singletonsCurrentlyInCreation.add(beanName)
         beforeSingletonCreation(beanName);

         boolean newSingleton = false;
         boolean recordSuppressedExceptions = (this.suppressedExceptions == null);

         // 删除代码
         ....

         try {
             .


            singletonObject = singletonFactory.getObject();
            newSingleton = true;
         }
         catch (IllegalStateException ex) {

            // 删除代码
            ....
         }
         catch (BeanCreationException ex) {

            // 删除代码
            ....
         }
         finally {

            // 删除代码
            ....

            afterSingletonCreation(beanName);
         }
         if (newSingleton) {
            addSingleton(beanName, singletonObject);
         }
      }
      return singletonObject;
   }
}

这句代码先留着,后边一并解释。

Object singletonObject = this.singletonObjects.get(beanName);

beforeSingletonCreation(beanName);这里会把 beanName 放入 singletonsCurrentlyInCreation 集合,表示这个 Bean 在实例化。

protected void beforeSingletonCreation(String beanName) {
   // 在这正在实例化 Bean 会被加入到 singletonsCurrentlyInCreation 集合
   if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
      throw new BeanCurrentlyInCreationException(beanName);
   }
}

在这行代码singletonObject = singletonFactory.getObject();执行完后,singletonObject 变量接收的就是实例化好的 Bean

实例化好后,newSingleton = true;标记有一个新的 Bean 生成,在最后面使用到了这个变量。

if (newSingleton) {
    addSingleton(beanName, singletonObject);
}


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

也就是说每个实例化好的 Bean, 都会放到这个集合里面,作为 Spring 的缓存。“从 Spring 容器里取出一个 Bean”,狭义上说的容器就是这个 singletonObjects 集合。看到这里你应该明白,这并不能代表 Spring 容器,只是容器里的一个 Map,专门被用来保存实例化好的 Bean,可以被认作为缓存。因此你会看到,Spring 在前面多次从这个 Map 中取 Bean,其实就是检查这个 Bean 有没有被实例化;如果实例化了,就不需要在走这么复杂的步骤,提高效率。

/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

加入 Map 之前,还有一行代码afterSingletonCreation(beanName);,在finally代码块里。

protected void afterSingletonCreation(String beanName) {
   if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
      throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
   }
}

这里最重要的一步就是把 beanName 移出了 singletonsCurrentlyInCreation 集合,因为这个 Bean 已经实例化完成。

createBean

singletonObject = singletonFactory.getObject();这里调用的是前面 Lamber 表达式中的 return createBean(beanName, mbd, args);这行代码。

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   // 删除代码
   ....

   RootBeanDefinition mbdToUse = mbd;

   // 删除代码
   ....

   try {
      // 开始创建 Bean
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);

      if (logger.isTraceEnabled()) {
         logger.trace("Finished creating instance of bean '" + beanName + "'");
      }
      return beanInstance;
   }
   catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
       // 删除代码
       ....
   }
   catch (Throwable ex) {
       // 删除代码
       ....
   }
}

跟进 doCreateBean 方法

doCreateBean

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
      throws BeanCreationException {

   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;

   if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }

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

   // 删除代码
   ....

   Object exposedObject = bean;

   // 删除代码
   ....

   return exposedObject;
}

如果是单例,则先把缓存中那一份移除。注意 factoryBeanInstanceCache 保存不是 Bean 实例,是包装了 Bean 实例的 BeanWrapper。其实也不算移除,算是取出来,如果存在,说明已经实例化过了,跳过实例化步骤。没有进入实例化instanceWrapper = createBeanInstance(beanName, mbd, args);

createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {

   // 删除代码
   ....

   // No special handling: simply use no-arg constructor.
   return instantiateBean(beanName, mbd);
}

前面是推断构造方法的过程,这里的推断构造方法不是想象那样,取出构造方法,后面文章会分析,直接到最后 instantiateBean(beanName, mbd);

instantiateBean

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
   try {
      Object beanInstance;
      final BeanFactory parent = this;
      if (System.getSecurityManager() != null) {
         beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
               getInstantiationStrategy().instantiate(mbd, beanName, parent),
               getAccessControlContext());
      }
      else {
         beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
      }
      BeanWrapper bw = new BeanWrapperImpl(beanInstance);
      initBeanWrapper(bw);
      return bw;
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
   }
}

不管走进哪个判断,都是执行getInstantiationStrategy().instantiate(mbd, beanName, parent);

instantiate

@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
   // Don't override the class with CGLIB if no overrides.
   if (!bd.hasMethodOverrides()) {
      Constructor<?> constructorToUse;
      synchronized (bd.constructorArgumentLock) {
            // 删除代码
            ....
            try {
               if (System.getSecurityManager() != null) {
                  constructorToUse = AccessController.doPrivileged(
                        (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
               }
               else {
                  constructorToUse = clazz.getDeclaredConstructor();
               }
               bd.resolvedConstructorOrFactoryMethod = constructorToUse;
            }
            catch (Throwable ex) {
               throw new BeanInstantiationException(clazz, "No default constructor found", ex);
            }
         }
      }
      return BeanUtils.instantiateClass(constructorToUse);
   }
   else {
       // 删除代码
       ....
   }
}

这一步是拿到默认构造方法,最明显的一行代码constructorToUse = clazz.getDeclaredConstructor();

instantiateClass

public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
   Assert.notNull(ctor, "Constructor must not be null");
   try {
         // 删除代码
         ....

         return ctor.newInstance(argsWithDefaultValues);
      }
   }
   catch (InstantiationException ex) {
       // 删除代码
       ....
   }
}

最后反射执行ctor.newInstance(argsWithDefaultValues);实例化 Bean

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值