Spring 源码学习 ② BeanFactory doGetBean 执行流程

spring-logo.png

Spring 源码学习 ② BeanFactory doGetBean 执行流程

Spring 源码系列文章会遵循由浅入深,由易到难,由宏观到微观的原则,目标是尽量降低学习难度,而不是一上来就迷失在源码当中. 文章会从一个场景作为出发点,针对性的目的性极强的针对该场景对 Spring 的实现原理,源码进行探究学习。该系列文章会让你收获什么? 从对 Spring 的使用者成为 Spring 专家。该文章会同步在微信公众号 【DevXJava】, 方便在微信客户端阅读。

本篇的内容是对 BeanFactory doGetBean 方法的探究,会涉及到一部分源码,但不会大量的讲解源码,目标是让读者对 doGetBean 方法中做的事情和流程有大致的宏观的认识。

场景

public class BeanFactoryGetBeanExp {

    public static void main(String[] args) throws Exception {

        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        // 在 beanFactory 中注册 bean1
        BeanDefinition bdf = BeanDefinitionBuilder.genericBeanDefinition(Bean1.class).getBeanDefinition();
        beanFactory.registerBeanDefinition("bean1" , bdf);
        
        for (String name : beanFactory.getBeanDefinitionNames()) {
            System.out.println("bean ----------> " + name);
        }

        // 调用 getBean , debug 进入观察获取 bean1 过程
        Bean1 bean1 = beanFactory.getBean(Bean1.class);
        System.out.println(bean1);

    }

    static class Bean1 {
        public Bean1() {
            System.out.println("Bean1 默认构造函数执行 >>>>>>>>>>>>>>>>>>>>>>");
        }
    }
}

这个场景非常简洁,首先我们提供了一个纯净的 DefaultListableBeanFactory , 通过 BeanDefinition Bean1 注册到 beanFactory 中; 完成注册后再从 beanFactory 中获取 Bean1 的实例.
为什么不使用 ApplicationContext ? 因为 ApplicationContext 实际上是对 BeanFactory 的封装 , Spring 自身在创建 ApplicationContext 会加入很多框架内置的配置。 为了排除干扰所以使用 BeanFactory .

doGetBean 执行过程

BeanFactory 所有的 getBean 方法最终都会去调用 doGetBean 方法, 所以我们只需要关注 doGetBean 方法即可。

BeanFactory#getBean.drawio (1).png

上图为 doGetBean 方法的大致执行流程,为了方便和源码对照查看学习,下面会附上 doGetBean 的源码;源码中会附上相应的中文注释说明;

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

   String beanName = transformedBeanName(name);
   Object beanInstance;

   // 从单例缓存中获取 bean 实例
   // Eagerly check singleton cache for manually registered singletons.
   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 实例进行处理
      beanInstance = 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);
      }

      // 尝试从父 BeanFactory 中获取 bean , 如果获取到会直接返回
      // Check if bean definition exists in this factory.
      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);
      }

      StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
            .tag("beanName", name);
      try {
         if (requiredType != null) {
            beanCreation.tag("beanType", requiredType::toString);
         }
         RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);

         // 检查 bean 是否存在循环引用 , 并初始化当前 bean 所依赖的 bean 实例
         
         // Guarantee initialization of beans that the current bean depends on.
         String[] dependsOn = mbd.getDependsOn();
         if (dependsOn != null) {
            for (String dep : dependsOn) {
               if (isDependent(beanName, dep)) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
               }
               registerDependentBean(dep, beanName);
               try {
                  getBean(dep);
               }
               catch (NoSuchBeanDefinitionException ex) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
               }
            }
         }

         // 这里开始真正进行 bean 的创建过程
         
         // Create bean instance.
         if (mbd.isSingleton()) {
         
            // 尝试从单例缓存(singletonObjects)中获取 bean , 如果没有获取到会进行 bean 的创建
            // bean 创建完成后会被存放到单例缓存中 (singletonObjects)
            
            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;
               }
            });
            beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
         }

         // 对范围为 Prototype 类型的 bean 进行创建,直接调用 createBean 方法进行创建
         else if (mbd.isPrototype()) {
            // It's a prototype -> create a new instance.
            Object prototypeInstance = null;
            try {
               beforePrototypeCreation(beanName);
               prototypeInstance = createBean(beanName, mbd, args);
            }
            finally {
               afterPrototypeCreation(beanName);
            }
            beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
         }

         // 通过 Scope 对 bean 进行创建
         else {
            String scopeName = mbd.getScope();
            if (!StringUtils.hasLength(scopeName)) {
               throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
            }
            Scope scope = this.scopes.get(scopeName);
            if (scope == null) {
               throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
            }
            try {
               Object scopedInstance = scope.get(beanName, () -> {
                  beforePrototypeCreation(beanName);
                  try {
                     return createBean(beanName, mbd, args);
                  }
                  finally {
                     afterPrototypeCreation(beanName);
                  }
               });
               beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
            }
            catch (IllegalStateException ex) {
               throw new ScopeNotActiveException(beanName, scopeName, ex);
            }
         }
      }
      catch (BeansException ex) {
         beanCreation.tag("exception", ex.getClass().toString());
         beanCreation.tag("message", String.valueOf(ex.getMessage()));
         cleanupAfterBeanCreationFailure(beanName);
         throw ex;
      }
      finally {
         beanCreation.end();
      }
   }

   // bean 创建成功后对 bean 进行类型转换后返回
   return adaptBeanInstance(name, beanInstance, requiredType);
}

更详细的细节过程以及源码会在系列文章的后续内容中提供。该文章会同步在微信公众号 【DevXJava】, 方便在微信客户端阅读。
获取完整代码和笔记: https://gitee.com/kernelHP/spring-certified-professional-edu

猜你喜欢

转载自blog.csdn.net/weixin_45839894/article/details/128788189
今日推荐