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

24 篇文章 17 订阅
22 篇文章 11 订阅

Spring 容器初始化

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

看上图,其中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初始化过程大概清楚一个整体流程
在这里插入图片描述

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

}

正常执行如下:
在这里插入图片描述
如果我修改下依赖,我要求X在创建的时候依赖Y

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

在这里插入图片描述
输出的效果就是先与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");
   }

}

在这里插入图片描述

这个错翻下上面的处理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的在后面的笔记中去记录,这篇笔记就到这里了。

  • 18
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值