欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring生命周期Bean初始化过程详解

程序员文章站 2022-06-03 08:51:13
...

Spring 容器初始化

在spring中,不管是以xml文件的方式配置的Bean还是以注解的方式进行配置,最后都会将单例Bean放入到Spring的容器中,这里说的单例池不是说放入的Bean都是单例的,而是spring在单例池中的Bean都是单例的,只要你从单例池中取Bean对象,那么整个生命周期过程中都只有一个实例,但是你放入单例池的对象Bean它不是单例的,你可以不借助spring而自己产生多例,但是一般都没有这么做,只是时候在概念上要理解单例池和单例类的区别,spring容器的整个启动到初始化过程如下:
Spring生命周期Bean初始化过程详解
后面还会根据一些过程进行详细画图,这篇笔记主要介绍下Bean的初始化过程

Spring Bean初始化

在spring容器中有两种Bean,一种是普通的Bean,一种是FactoryBean,在介绍Bean的初始化之前,我们要先来理解这两种Bean的区别

BeanFactory和FactoryBean

BeanFactory和FactoryBea的的理解,相信在百度上一搜一大堆,就是说着两个有什么区别呢?
BeanFactory是spring的容器中的Bean工厂,Bean的创建,获取都是它来完成的,也就是说BeanFactory就是spring的容器,里面放入了所有的Bean,包括单例Bean,原型的Bean定义,也就是BeanDefinition,而FactoryBean也是一种Bean,FactoryBean是BeanFactory的一种Bean,是一种特殊的Bean,FactoryBean中是只能放入一种类型的Bean,而BeanFactory中可以放入不同类型的Bean,我们先来看下FactoryBean接口提供的方法,也就是它本身定义了提供了那些功能:

public interface FactoryBean<T> {
    @Nullable
T getObject() throws Exception;

@Nullable
Class<?> getObjectType();

default boolean isSingleton() {
   return true;
}

getObject():该方法就是你通过factoryBean放入容器的对象,也就是当你getBean的时候返回的就是spring调用getObject返回的Bean对象;
getObjectType():FactoryBean代表返回对象的类型
isSingleton:这是factoryBean默认的方法,你不需要实现,当然你也可以实现,默认是单例的bean
我们平时开发工程中使用的比较多的Mybatis就是用了FactoryBean,大家可能都知道,Mybatis中的Mapper是一个接口,而接口在spring容器中是不能实例化的,所以Mybatis就是利用了FactoryBean来重新构建了对象(通过反射)
我们简单来看下FactoryBean的例子:

@Component
public class BmlFactoryBean<T> implements FactoryBean<T> {

   @SuppressWarnings(value = "unchecked")
   @Override
   public T getObject() throws Exception {
      return (T) new User();
   }

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

AnnotationConfigApplicationContext c = new AnnotationConfigApplicationContext();
c.register(AppConfig.class);
c.refresh();

System.out.println(c.getBean("bmlFactoryBean"));
输出:com.bml.entity.User@6107227e

输出的是User对象,所以FactoryBean获取Bean返回的是geteObject返回的对象,在spring容器中存在两个Bean,一个是FactoryBean对应的对象,一个是FactoryBean中getObject返回的对象,所以是有两个Bean,而且如果通过
c.getBean(“bmlFactoryBean”)不管获取几次都是相同的对象,这里有一个重要的概念,我们都知道FactoryBean创建的对象都是单例Bean,但是一般的@Coponent创建的Bean和FactoryBean创建的对象有什么不同吗?
其实在上面的代码中,User对象的真正创建不是在18行代码,而是在20行代码,虽然我们的FactoryBean默认是单例的,但是FactoryBean只有在第一次getBean的时候才会放入到单例池,也就是说FactoryBean默认是懒加载的
而在spring容器中最终会出现两个Bean,比如就上面的代码,那么beanName=bmlFactoryBean是对应的我们的User Bean对象,而beanName=&bmlFactoryBean对应的是我们的FactoryBean本身的Bean对象
Spring生命周期Bean初始化过程详解

看上图,其中BeanFactory中的单例池是singletonObjects是存放了加了@Coponent注解的单例Bean,而上面的代码的FactoryBean是放在了单例池中的,而FactoryBean中getObject返回的对象的Bean是放在了factoryBeanOjectCache中的,看上图几非常清楚了;而我们通过ApplicationContext的getBean去获取FactoryBean的时候,如果beanName前面加了&就表示获取本身的FactoryBean,而不加&则表示获取FactoryBean中的getObject返回的对象。

源码分析

Bean的实例化

Bean的实例化可以说spring里面最核心的也是比较复杂的,也是比较绕的地方,bean的实例化是在DefaultListableBeanFactory中的preInstantiateSingletons方法开始的,这篇笔记主要把bean的初始化过程简单过一遍,有些地方太多了,后面笔记会慢慢写,这里主要把这个方法的前几个过程记录一下。

preInstantiateSingletons

/**
    * 单例Bean的初始化
    *
    * @throws BeansException
    */
   @Override
   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.
      /**
       * beanNames就是spring扫描得到的所有beanName都放在一个集合list中在
       */
      List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

      // Trigger initialization of all non-lazy singleton beans...
      //然后根据beanNames循环开始初始化Bean
      for (String beanName : beanNames) {
         //这个过程就是合并bean的过程,合并bean的过程有点绕,反正流程就是将Bean合并成了一个RootBeanDefinition
         //因为spring在扫描的过程中会把Bean扫描成GenericBeanDefinition,GenericBeanDefinition是
         //可以设置父子bean的,而RootBeanDefinition设置父亲BeanName的时候会直接报错的,因为
         //RootBeanDefinition是*BeanDefinition,是没有父亲Bean的
         RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
         //判断这个Bean不能是抽象的,不是延迟加载的,并且是单例的bean才会进行初始化
         if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            //实例化的第一步是先看下你是不是FactoryBean
            if (isFactoryBean(beanName)) {
               //如果是FactoryBean,这里就是FactoryBean的一个很重要的概念了,下面的代码
               //Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);这里是在创建单例Bean,但是请注意,这里创建的Bean是FactoryBean,它只是spring容器中一个普通Bean
               //这里创建的bean只是FactoryBean本身,比如我们的DemoFactoryBean,那么这里创建的就是DemoFactoryBean本身的对象,而不是它getObject()方法返回的对象bean
               //所以针对FactoryBean来说,FactoryBean本身对象的beanName是以&beanName形式存在的,但是请注意,在缓存map中还是去掉了&的,都是以beanName的形式存在的
               //如果是factoryBean,并且是单例的bean,那么factoryBean本身的对象存在signletonObjects,而factoryBean的getobject返回的对象在factoryBeanObjectCache中
               Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
               if (bean instanceof FactoryBean) {
                  FactoryBean<?> factory = (FactoryBean<?>) bean;
                  //这个变量isEagerInit是什么意思呢?它的意思就是表示是不是马上加载的意思,用在这里我们猜一猜也就知道了
                  //你想哈,我们知道FactoryBean虽然设置为单例的,但是其实得到factoryBean的getobject对象是在你在getBean的时候并且beanName没有带&才会去创建
                  //简单来说,就是facatoryBean是懒加载的,下面的这个参数的意思就是说你是不是要马上加载,不是懒加载,而是马上加载到容器中
                  boolean isEagerInit;
                  if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                     isEagerInit = AccessController.doPrivileged(
                           (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
                           getAccessControlContext());
                  } else {
                     //注意看这个代码,这个代码的意思就是说你的FactoryBean是不是SmartFactoryBean,
                     //SmartFactoryBean也是一个Factorybean,但是它比FactoryBean多了一个功能就是可以设置为非懒加载的,也就是立马初始化
                     isEagerInit = (factory instanceof SmartFactoryBean &&
                           ((SmartFactoryBean<?>) factory).isEagerInit());
                  }
                  if (isEagerInit) {
                     //初始化Bean
                     getBean(beanName);
                  }
               }
            } else {
               //初始化Bean
               getBean(beanName);
            }
         }
      }

      // Trigger post-initialization callback for all applicable beans...
      //bean初始化完成过后,单例bean初始化的回调方法,但是要实现了SmartInitializingSingleton才有
//    /实现该接口后,当所有单例 bean 都初始化完成以后, 容器会回调该接口的方法 afterSingletonsInstantiated。
//主要应用场合就是在所有单例 bean 创建完成之后,可以在该回调中做一些事情
      for (String beanName : beanNames) {
         Object singletonInstance = getSingleton(beanName);
         if (singletonInstance instanceof SmartInitializingSingleton) {
            SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            if (System.getSecurityManager() != null) {
               AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                  smartSingleton.afterSingletonsInstantiated();
                  return null;
               }, getAccessControlContext());
            } else {
               smartSingleton.afterSingletonsInstantiated();
            }
         }
      }
   }

我这里画了一个简单的图,自己画的图可能不太准确,但是基本上也覆盖了bean初始化的一些过程,其中getBean没有详细的流程图,因为getBean这个太复杂了,后面会根据getBean再细化,这篇笔记主要讲bean初始化过程大概清楚一个整体流程
Spring生命周期Bean初始化过程详解

getMergedLocalBeanDefinition

合并bean的方法,很多解释我都写在代码注释里面了,这里就不多废话了

protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
   // Quick check on the concurrent map first, with minimal locking.
   //先从合并的BeanDefinition的缓存中取RootBeanDefinition看有没有,没有才去创建
   RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
   if (mbd != null && !mbd.stale) {
      return mbd;
   }
   return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
/**
    * Return a RootBeanDefinition for the given bean, by merging with the
    * parent if the given bean's definition is a child bean definition.
    * @param beanName the name of the bean definition
    * @param bd the original bean definition (Root/ChildBeanDefinition)
    * @param containingBd the containing bean definition in case of inner bean,
    * or {@code null} in case of a top-level bean
    * @return a (potentially merged) RootBeanDefinition for the given bean
    * @throws BeanDefinitionStoreException in case of an invalid bean definition
    * 合并Bean的真正逻辑,涉及的概念,父子容器、父子Bean合并,非父子Bean,
    * 将GenericBeanDefinition单独封装成一个RootBeanDefinition
    */
   //参数containingBd就表示合并过后的bean,什么意思呢?就是如果你传入的containingBd不为空,则就不用合并了
   //它本身就是一个合并过后的bean
   protected RootBeanDefinition getMergedBeanDefinition(
         String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
         throws BeanDefinitionStoreException {

      //线程安全来处理逻辑
      synchronized (this.mergedBeanDefinitions) {
         RootBeanDefinition mbd = null;
         RootBeanDefinition previous = null;

         // Check with full lock now in order to enforce the same merged instance.
         if (containingBd == null) {
            //如果containingBd为空,则重新去合并bean的缓存池重新拿RootBeanDefinition
            mbd = this.mergedBeanDefinitions.get(beanName);
         }

         if (mbd == null || mbd.stale) {
            previous = mbd;
//          这里判断你传入的bd是否存在父子关系,这里我们需要知道的是GenericBeanDefinition中是可以设置parentName的
            //也就是说可以设置父亲BeanId,而RootBeanDefinition是不能设置的,设置直接报错,这个概念要理解清楚
            //下面的逻辑就是说你传入的bd如果本身就是一个RootBeanDefinition,那么直接返回
            //如果不是,那么就强制封装一个RootBeanDefinition返回给你
            if (bd.getParentName() == null) {
               // Use copy of given root bean definition.
               if (bd instanceof RootBeanDefinition) {
                  mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
               }
               else {
                  mbd = new RootBeanDefinition(bd);
               }
            }
            else {
               // Child bean definition: needs to be merged with parent.
               //代码逻辑到这里的时候就表示存在父子关系的bean,通过父亲的Beanname递归调用getMergedBeanDefinition
               //因为你的父子Bean可能存在多层关系,父子的父子的父子是有可能存在的,所以这里是递归,如果说孩子的beanName和
               //父亲的beanName一样,那么可能会出现在父子容器,就是说我的父亲可能在父容器里面,所以else就是去父容器
               //中找寻这个bean,也是一样的逻辑,在父亲的容器中递归获取Bean
               BeanDefinition pbd;
               try {
                  String parentBeanName = transformedBeanName(bd.getParentName());
                  if (!beanName.equals(parentBeanName)) {
                     pbd = getMergedBeanDefinition(parentBeanName);
                  }
                  else {
                     BeanFactory parent = getParentBeanFactory();
                     if (parent instanceof ConfigurableBeanFactory) {
                        pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
                     }
                     else {
                        throw new NoSuchBeanDefinitionException(parentBeanName,
                              "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
                              "': cannot be resolved without a ConfigurableBeanFactory parent");
                     }
                  }
               }
               catch (NoSuchBeanDefinitionException ex) {
                  throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
                        "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
               }
               // Deep copy with overridden values.
               //到这里就是合并bean了,声明一个RootBeanDefinition,然后将子bean的属性都设置到mbd中
               //这样就完成了一个合并,也不能说合并,就是创建了一个新的RootBeanDefinition,然后这个beanDefinition是
               //包含了父子合成的属性存在于容器中的,而原来的父亲的bean在容器中也没有改变,因为这里是new的一个
               //所以之前的那个父亲的beanDefinition也是没有改变的,还是在原来的容器中,这里是新创建的
               mbd = new RootBeanDefinition(pbd);
               mbd.overrideFrom(bd);
            }

            // Set default singleton scope, if not configured before.
            if (!StringUtils.hasLength(mbd.getScope())) {
               mbd.setScope(SCOPE_SINGLETON);
            }

            // A bean contained in a non-singleton bean cannot be a singleton itself.
            // Let's correct this on the fly here, since this might be the result of
            // parent-child merging for the outer bean, in which case the original inner bean
            // definition will not have inherited the merged outer bean's singleton status.
            if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
               mbd.setScope(containingBd.getScope());
            }

            // Cache the merged bean definition for the time being
            // (it might still get re-merged later on in order to pick up metadata changes)
//          合并过后的RootBeanDefinition,放入到mergedBeanDefinitions缓存中
            if (containingBd == null && isCacheBeanMetadata()) {
               this.mergedBeanDefinitions.put(beanName, mbd);
            }
         }
         if (previous != null) {
            copyRelevantMergedBeanDefinitionCaches(previous, mbd);
         }
         return mbd;
      }
   }

getBean方法

//这个方法特别长,因为这个方法包含了创建bean,获取bean
/**
 * Return an instance, which may be shared or independent, of the specified bean.
 * @param name the name of the bean to retrieve
 * @param requiredType the required type of the bean to retrieve
 * @param args arguments to use when creating a bean instance using explicit arguments
 * (only applied when creating a new instance as opposed to retrieving an existing one)
 * @param typeCheckOnly whether the instance is obtained for a type check,
 * not for actual use
 * @return an instance of the bean
 * @throws BeansException if the bean could not be created
 * 这里是创建Bean,在spring启动容器的过程中可能会调用多次,同一个Bean的创建可能会创建多次,因为可能会出现循环依赖
 */
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
      String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
      throws BeansException {

   //对beanName进行处理,看是否是带了&字符和这个name是不是以别名的形式传入的
   String beanName = transformedBeanName(name);
   Object bean;

   // Eagerly check singleton cache for manually registered singletons.
   //getSingleton是从单例池中获取,是根据Beanname去获取,如果第一次肯定为空
   Object sharedInstance = getSingleton(beanName);
   if (sharedInstance != null && args == null) {
      if (logger.isTraceEnabled()) {
         if (isSingletonCurrentlyInCreation(beanName)) {
            logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                  "' that is not fully initialized yet - a consequence of a circular reference");
         }
         else {
            logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
         }
      }
      //如果单例池中获取到了对象,那么根据下面的代码去判断这个对象是不是factoryBean,如果是factorybean
      //
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }

   else {
      // Fail if we're already creating this bean instance:
      // We're assumably within a circular reference.
      //和循环依赖有关,后面说
      if (isPrototypeCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(beanName);
      }

      // Check if bean definition exists in this factory.
      //下面的if else逻辑就是去父容器中找看是否有,找到就直接返回
      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);
         }
      }

      if (!typeCheckOnly) {
         markBeanAsCreated(beanName);
      }

      try {
         //beanName在容器中还不存在,然后在父工厂也不存在,那么就会走到这里
         RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);

         // Guarantee initialization of beans that the current bean depends on.
         //下面就是看beanName是否有设置依赖,这个依赖是强依赖,是程序员自己设置的强依赖,强依赖简单理解就是我在初始化自己的时候,看下有没有强依赖的bean,如果有
         //那么先去实例化依赖的bean,这样我们可以做一些自己的事情,比如我的实例化必须要依赖于某个bean,就可以这样使用
         String[] dependsOn = mbd.getDependsOn();
         if (dependsOn != null) {
            for (String dep : dependsOn) {
               //这里是判断我依赖的ban有没有依赖我,简单来说就是我们两个Bean有没有相互依赖,也就是说循环依赖,如果存在循环依赖,直接报错
               //这里的循环依赖不是bean组合额循环依赖,组合使用的循环依赖spring是可以解决的,但是@DependOn是没有办法解决的
               if (isDependent(beanName, dep)) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
               }
               //登记当前beanName依赖的的beanName dep
               registerDependentBean(dep, beanName);
               try {
                  //实例化要依赖的bean
                  getBean(dep);
               }
               catch (NoSuchBeanDefinitionException ex) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
               }
            }
         }

         /**
          * 上面一直没有获取到bean对象,并且处理了依赖的ban,下面就开始处理自己了
          *下面的逻辑就是根据作用域去获取创建bean
          * 1.单例bean
          * 2.原型bean
          * 3.web bean(scope=request or session),在spring mvc中使用
          */
         // Create bean instance.
         if (mbd.isSingleton()) {
            //如果是单例的,下面的代码上面说过了,反正就是创建bean,createBean这个方法最核心,也太复杂,包括后续的执行流程都在里面
            //这个createBean方法后面还有笔记要写很久
            sharedInstance = getSingleton(beanName, () -> {
               try {
                  return createBean(beanName, mbd, args);
               }
               catch (BeansException ex) {
                  // Explicitly remove instance from singleton cache: It might have been put there
                  // eagerly by the creation process, to allow for circular reference resolution.
                  // Also remove any beans that received a temporary reference to the bean.
                  destroySingleton(beanName);
                  throw ex;
               }
            });
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
         }

         else if (mbd.isPrototype()) {
            //如果是原型的bean,那么这里进行创建
            // It's a prototype -> create a new instance.
            Object prototypeInstance = null;
            try {
               beforePrototypeCreation(beanName);
               prototypeInstance = createBean(beanName, mbd, args);
            }
            finally {
               afterPrototypeCreation(beanName);
            }
            bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
         }

         else {
            //代码走到这里,则证明你的这个bean不是单例的,也不是原型的,而是rquest或者session的bean
            String scopeName = mbd.getScope();
            if (!StringUtils.hasLength(scopeName)) {
               throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
            }
            //scopes中存放了request bean和sessionbean的beanNames
            Scope scope = this.scopes.get(scopeName);
            if (scope == null) {
               throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
            }
            try {
               //创建request bean或者sessionBean,下面的代码是lambad表达式,也就是get方法需要有一个参数Objectfactory,也就是具体的实例
               //这里简单说下这里面的逻辑,里面的逻辑简单来说就是通过获取到的objectInstance
               //然后使用request.getAttrbute(beanName)获取,如果获取到了就返回吗,没如果没有获取到,通过lambad表达式返回的bean对象,
               //然后放入request或者session中,然后返回
               //这里重要的是这个bean是在request中或者session中,取决于你的scope属性
               //spring这里巧妙的使用了web的特性来存储web 创建的bean
               Object scopedInstance = scope.get(beanName, () -> {
                  beforePrototypeCreation(beanName);
                  try {
                     return createBean(beanName, mbd, args);
                  }
                  finally {
                     afterPrototypeCreation(beanName);
                  }
               });
               bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
            }
            catch (IllegalStateException ex) {
               throw new BeanCreationException(beanName,
                     "Scope '" + scopeName + "' is not active for the current thread; consider " +
                     "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                     ex);
            }
         }
      }
      catch (BeansException ex) {
         cleanupAfterBeanCreationFailure(beanName);
         throw ex;
      }
   }

   // Check if required type matches the type of the actual bean instance.
   if (requiredType != null && !requiredType.isInstance(bean)) {
      try {
         T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
         if (convertedBean == null) {
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
         }
         return convertedBean;
      }
      catch (TypeMismatchException ex) {
         if (logger.isTraceEnabled()) {
            logger.trace("Failed to convert bean '" + name + "' to required type '" +
                  ClassUtils.getQualifiedName(requiredType) + "'", ex);
         }
         throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
      }
   }
   return (T) bean;
}

getObjectForBeanInstance

getObjectForBeanInstance方法比较重要,spring这里每次获取bean后都要调用它,就是为了知道到底是一个普通bean还是factorybean的获取,如果是普通bean的获取,直接返回,如果是factorybean的获取,要去factoryBeanObjectCache中获取
/**
    * Get the object for the given bean instance, either the bean
    * instance itself or its created object in case of a FactoryBean.
    * @param beanInstance the shared bean instance
    * @param name the name that may include factory dereference prefix
    * @param beanName the canonical bean name
    * @param mbd the merged bean definition
    * @return the object to expose for the bean
    * 这里传入的参数name=原生传入的beanName没有做过处理的beanName,而beanName是经过处理过后的beanName
    */
   protected Object getObjectForBeanInstance(
         Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

      // Don't let calling code try to dereference the factory if the bean isn't a factory.
      //这里判断的时候你的元素name是不是以&开头,如果是,则证明你要获取的是factoryBean本身的对象,而不是factoryBean的getObject
      //要返回的对象
      if (BeanFactoryUtils.isFactoryDereference(name)) {
         /**
          * 下面的判断分为几步:
          * 1.你这个Bean是factoryBean了,判断从单例池中获取到的对象是不是NullBean,如果是,直接返回
          * 2.如果不是NullBean,那么你必须是FactoryBean,否则直接报错
          * 3.否则就直接返回
          */
         if (beanInstance instanceof NullBean) {
            return beanInstance;
         }
         if (!(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
         }
         if (mbd != null) {
            mbd.isFactoryBean = true;
         }
         return beanInstance;
      }

      // Now we have the bean instance, which may be a normal bean or a FactoryBean.
      // If it's a FactoryBean, we use it to create a bean instance, unless the
      // caller actually wants a reference to the factory.
      //这里再次判断了一下,如果上面的代码没有执行,也就是说你的beanname不是&开头的,beanInstance也不是FactoryBean
      //类型,如果不是factoryBean,就直接返回bean对象本身
      if (!(beanInstance instanceof FactoryBean)) {
         return beanInstance;
      }

      /**
       * 到下面的逻辑就证明就是一个FactoryBean了,并且是要获取FactoryBean中getObject返回的对象
       */

      Object object = null;
      if (mbd != null) {
         mbd.isFactoryBean = true;
      }
      else {
         //从factoryBeanObjectCache中获取对象,factoryBeanObjectCache是放了FactoryBean中getObject返回的对象的缓存
         object = getCachedObjectForFactoryBean(beanName);
      }
      //如果没有拿到对象,也就是在factoryBeanObjectCache中没有获取到,则证明是第一次,那么这里
      //去调用FactoryBean中的getObject返回拿到bean对象
      if (object == null) {
         // Return bean instance from factory.
         FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
         // Caches object obtained from FactoryBean if it is a singleton.
         //这里还涉及到一个重要的知识点,就是合并bean的概念,spring中扫描得到的BeanDefinition是GenericBeanDefinition,
         //而合并过后就是一个RootBeanDefinition,所以如果传入的mbd为空,则证明还没有合并过这个Bean,那么我们要明白只要进入
         //单例池创建的Bean,都是通过RootBeanDefinition来进行创建的,所以这里有一个重要的概念就是如果这个Bean还没有合并过
//       那么这里就需要合并一下,合并Bean一个重要概念就是父子Bean,当然以注解方式的配置的Bean,目前好像还没有配置父子Bean的地方
         //但是在xml方式的时候就会有,如果合并bean的过程中,发现没有父子Bean,那么也会封装一个RootBeanDefinition
         //如果有父子Bean,那么这里会将父子Bean合并,也就是将子Bean的属性填充到父Bean里面成为一个完整的Bean
         if (mbd == null && containsBeanDefinition(beanName)) {
            mbd = getMergedLocalBeanDefinition(beanName);
         }
         boolean synthetic = (mbd != null && mbd.isSynthetic());
         //这个方法里的代码就非常简单了,就是通过FactoryBean的getObject方法获取返回的对象,然后将这个对象放入到了
         //FactoryBean的缓存factoryBeanObjectCache中
         object = getObjectFromFactoryBean(factory, beanName, !synthetic);
      }
      return object;
   }

getObjectFromFactoryBean方法就是去factoryBeanObjectCache获取,如果factoryBeanObjectCache没有,则调用factoryBean的getobject方法,然后将调用返回的object 放置到factoryBeanObjectCache中,最后返回

例子分析

@DependsOn

在spring的容器中,程序员手动配置的强制依赖可以通过@DependsOn,就是说可以在一个bean在创建的时候先创建依赖的bean,在上面的代码注释中已经很详细的说明了这个作用,这边来做一个例子

@Component
public class X {
   public X(){
      System.out.println("Create X ");
   }
}
@Component
public class Y {

   @Autowired
   private X x;
   public Y(){
      System.out.println("Create Y");
   }

}

正常执行如下:
Spring生命周期Bean初始化过程详解
如果我修改下依赖,我要求X在创建的时候依赖Y

@Component
@DependsOn("y")
public class X {
   public X(){
      System.out.println("Create X ");
   }
}

Spring生命周期Bean初始化过程详解
输出的效果就是先与Y创建,再创建X,那么spring源码中对@DependsOn的循环依赖是什么呢?就是X依赖Y,而Y又依赖了X,这就导致了循环依赖,在@DependsOn中的循环依赖是没有办法解决的,spring会直接报错,比如:

@Component
@DependsOn("x")
public class Y {

   @Autowired
   private X x;
   public Y(){
      System.out.println("Create Y");
   }

}

Spring生命周期Bean初始化过程详解

这个错翻下上面的处理DependsOn的时候有这个异常的 ,所以spring是没有办法处理@DependsOn的循环依赖的;
下面我们看下DependsOn的源码:

protected boolean isDependent(String beanName, String dependentBeanName) {
   //dependentBeanMap存放的是我当前beanName被那些beanName依赖了,这个是在扫描阶段完成的
   synchronized (this.dependentBeanMap) {
      return isDependent(beanName, dependentBeanName, null);
   }
}
private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
      if (alreadySeen != null && alreadySeen.contains(beanName)) {
         return false;
      }
      //这里是怕你传入的是bean的别名,所以这里是处理别名的
      String canonicalName = canonicalName(beanName);
      //获取beanName被依赖的beanNames集合
      Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
      if (dependentBeans == null) {
         return false;
      }
      //如果被我依赖的beanNames中还包含了我,那么就是循环依赖
      if (dependentBeans.contains(dependentBeanName)) {
         return true;
      }
//    如果上面的条件不满足,就循环递归去检查
      for (String transitiveDependency : dependentBeans) {
         if (alreadySeen == null) {
            alreadySeen = new HashSet<>();
         }
         alreadySeen.add(beanName);
         if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
            return true;
         }
      }
      return false;
   }

到这里,初始化过程就差不多了,getBean里面的最难也是最核心的createBean的在后面的笔记中去记录,这篇笔记就到这里了。