Spring源码分析四:Bean加载总览①

Spring源码分析四:Bean加载总览①,第1张

文章目录
  • (一)序言
  • (二)Spring初始化非延迟加载单例入口
    • 1、初始化非延迟加载单例bean准备:finishBeanFactoryInitialization
    • 2、实例化单例bean:preInstantiateSingletons
  • (三)Spring Bean加载
    • 1、非延迟bean加载:doGetBean
  • (四)非延迟加载bean流程

(一)序言

Spring源码分析容器篇中初始化非延迟加载单例finishBeanFactoryInitialization中提到了大概,在容器篇中未进行详细分析,本文是对spring初始化非延迟加载单例详细分析,也是笔者对spring深入学习的过程,文中有出错的地方,还望大家能够及时指出。

(二)Spring初始化非延迟加载单例入口

本次入口分析是Spring容器篇中第11步finishBeanFactoryInitialization->preInstantiateSingletons方法,初始化非延迟加载单例方法是包含了处理参数绑定、处理LoadTimeWeaverAware类型的Aop和加载饿汉式单例bean,主要是由preInstantiateSingletons方法来加载单例bean,加载饿汉式单例是本文重点分析的对象。

1、初始化非延迟加载单例bean准备:finishBeanFactoryInitialization

初始化bean常规饿汉式单实例bean即非惰性的bean,经典的getBean方法被调用,代码执行到此处,BeanFactory已经创建完成,并且所有的实现了BeanFactoryPostProcessor接口的Bean都已经初始化并且其中的postProcessBeanFactory(factory)方法已经得到回调执行了。而且Spring已经“手动”注册了一些特殊的Bean,如environment、systemProperties、监听器等等。剩下的就是初始化所有的单例bean,大都数我们的业务中都是单例bean,就像我们写的@Controller、@Service的类(没有设置懒加载的)都是在这个地方初始化,以供我们使用,如果没有设置懒加载,那么Spring会在接下来初始化所有的singleton beans。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    /**
     * 容器中有配置bean名称为conversionService时,则使用getBean对其进行初始化
     * conversionService类是将前端传过来的参数和后端的controller方法上的参数进行绑定的时候用
     */
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
            beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
        beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME,ConversionService.class));
    }
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }
    //获取LoadTimeWeaverAware类型的,主要是Aop的实现原理
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName);
    }
    //清空临时类加载器
    beanFactory.setTempClassLoader(null);
    //暂停临时的类加载器使用
    beanFactory.freezeConfiguration();
    //委托给DefaultListableBeanFactory去实例化非懒加载的单例bean(核心)
    beanFactory.preInstantiateSingletons();
}
2、实例化单例bean:preInstantiateSingletons

DefaultListableBeanFactory类负责实现preInstantiateSingletons预加载实例化单例bean,只处理非抽象、单例且非懒加载的bean,包含工厂bean和单例bean,最后实例化完所有的单例bean后,如果每一个bean是否有实现SmartInitializingSingleton接口,如果有实现则执行回调方法afterSingletonsInstantiated,具体逻辑如下:

public void preInstantiateSingletons() throws BeansException {
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);//获取所有的BeanDefinitionNames
    for (String beanName : beanNames) {//遍历beanNames
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);//获得BeanDefinition
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {//只处理非抽象、单例且非懒加载
            if (isFactoryBean(beanName)) {//判断是否为工厂bean
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);//工厂bean时需要使用&作为前缀
                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());
                    }
                    //是否加载工厂bean
                    if (isEagerInit) {
                        getBean(beanName);
                    }
                }
            }else {
                //处理非工厂bean即饿汉式加载单例bean,核心点重点分析
                getBean(beanName);
            }
        }
    }
    //触发加载后的所有单例bean的后置afterSingletonsInstantiated方法即回调
    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();
            }
        }
    }
}
(三)Spring Bean加载 1、非延迟bean加载doGetBean

AbstractBeanFactory类来负责完成加载非延迟单例bean——getBean,实际由doGetBean来完成,其中核心点为规范化beanName、getSingleton缓存获取bean实例、自定义容器与spring的AbstractBeanFactory递归获取bean、优化缓存bean、处理depend-on依赖实例化、创建除单例的bean和检查返回的bean类型,代码具体逻辑如下:

public Object getBean(String name) throws BeansException {
	//封装获得bean,实际实现由doGetBean
	return doGetBean(name, null, null, false);
}

Spring特点之一,概念性且比较重要的统一使用方法封装,底层基本都是由doXXX来实现,下面具体重点分析doGetBean核心逻辑,代码如下:

protected <T> T doGetBean(String name, Class<T> requiredType,Object[] args, boolean typeCheckOnly)
      throws BeansException {
  //spring别名转化,工厂beanName转化为实际的beanName(1)
  String beanName = transformedBeanName(name);
  Object bean;
  //从缓存中获取bean,一级缓存、二级缓存、三级缓存,后面开展循环依赖文章中重点分析(2)
  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 + "'");
          }
      }
       /**
        * 返回bean实例,sharedInstance可能是FactoryBean或普通bean实例
        * 如果是是工厂bean则执行getObject返回,否则直接返回普通bean实例
        */
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
  }else {
      //判断是否为原型bean,只处理单例
      if (isPrototypeCurrentlyInCreation(beanName)) {
          throw new BeanCurrentlyInCreationException(beanName);
      }
      //spring容器中不存在当前bean,则进行一系列准备工作,开始着手创建bean实例
      BeanFactory parentBeanFactory = getParentBeanFactory();//获取父类容器
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
          //获取beanName,此处与transformedBeanName获取beanName不同,会返回普通bean和工厂bean的beanName
          String nameToLookup = originalBeanName(name);
          if (parentBeanFactory instanceof AbstractBeanFactory) {
              /**
               * 父类容器中获取bean即AbstractBeanFactory中的doGetBean,此处其实是防止自定义容器实现doGetBean中未找到
               * 则在AbstractBeanFactory容器中再次获取
               * (3)
               */
              return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                      nameToLookup, requiredType, args, typeCheckOnly);
          } else if (args != null) {
              // 有参数args时则委托给父类容器获取bean
              return (T) parentBeanFactory.getBean(nameToLookup, args);
          } else if (requiredType != null) {
              // 无参数时且requiredType不为空也委托给父类容器获取bean
              return parentBeanFactory.getBean(nameToLookup, requiredType);
          } else {
              //不满足上述if和else if条件时则默认使用父类容器获取bean
              return (T) parentBeanFactory.getBean(nameToLookup);
          }
      }
      //getBean方法typeCheckOnly默认值为false,主要是优化缓存bean,不重复创建bean(4)
      if (!typeCheckOnly) {
          /**
           * markBeanAsCreated中使用alreadyCreated变量负责检查bean是否为已创建或正在创建
           * 如果是则改变BeanDefinition的stale为true,该值会控制是否创建
           */
          markBeanAsCreated(beanName);
      }
      try {
          //获取RootBeanDefinition,包含了自身容器和父类容器中获取
          RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
          checkMergedBeanDefinition(mbd, beanName, args);//检查该RootBeanDefinition是否为抽象标记,如果是则抛出异常
          // 获取该BeanDefinition的依赖属性
          String[] dependsOn = mbd.getDependsOn();
          if (dependsOn != null) {
              for (String dep : dependsOn) {
                  /**
                   * isDependent方法检查该bean是否有循环依赖,如果存在相互先实例化的关系则抛出异常
                   * 此处的depends-on属性中是指当前bean实例化之前必须先实例化该属性值中bean,与我们常说的循环依赖是不一样的
                   * 该处仅仅是检查该bean必须在另一个bean实例化的前面,可以被注入也可以不被注入
                   * (5)
                   */
                  if (isDependent(beanName, dep)) {
                      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                              "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                  }
                  registerDependentBean(dep, beanName);//将其注册到dependenciesForBeanMap中
                  try {
                      getBean(dep);//开始实例化属性bean
                  } catch (NoSuchBeanDefinitionException ex) {
                      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                              "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                  }
              }
          }
          //开始真正创建单例bean
          if (mbd.isSingleton()) {
              //使用lamda表达式来获取bean
              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实例,sharedInstance可能是FactoryBean或普通bean实例
               * 如果是是工厂bean则执行getObject返回,否则直接返回普通bean实例
               */
              bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
          } else if (mbd.isPrototype()) {
              //处理bean为prototype类型的,直接创建(6)
              Object prototypeInstance = null;
              try {
                  beforePrototypeCreation(beanName);//创建原型bean前将自身添加到prototypesCurrentlyInCreation中
                  prototypeInstance = createBean(beanName, mbd, args);
              } finally {
                  afterPrototypeCreation(beanName);//创建原型bean后将自身从prototypesCurrentlyInCreation中移除
              }
               /**
               * 返回bean实例,sharedInstance可能是FactoryBean或普通bean实例
               * 如果是是工厂bean则执行getObject返回,否则直接返回普通bean实例
               */
              bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
          } else {
              //其他作用域的bean,request或session作用域(6)
              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 {
                  //直接创建新的bean实例,沿用beforePrototypeCreation和afterPrototypeCreation来标记创建过程
                  Object scopedInstance = scope.get(beanName, () -> {
                      beforePrototypeCreation(beanName);
                      try {
                          return createBean(beanName, mbd, args);
                      } finally {
                          afterPrototypeCreation(beanName);
                      }
                  });
                  //返回bean实例,可能是FactoryBean或普通bean实例
                  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;
      }
  }
  // 检查获取bean时是否匹配指定返回的Class类型(7)
  if (requiredType != null && !requiredType.isInstance(bean)) {
      try {
          //转化为requiredType类型,如果有自定义转换器时会很有效果
          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;
}
(四)非延迟加载bean流程

(1)规范化beanName:transformedBeanName方法负责普通bean的别名或去除工厂bean的前缀转化为beanName;
(2)getSingleton缓存获取bean实例:从缓存中获取bean,一级缓存(singletonObjects)、二级缓存(earlySingletonObjects)、三级缓存(singletonFactories);
(3)自定义容器与spring的AbstractBeanFactory递归获取bean:父类容器中获取bean即AbstractBeanFactory中的doGetBean,此处其实是防止自定义容器实现doGetBean中未找到则在AbstractBeanFactory容器中再次获取;
(4)优化缓存bean:getBean方法typeCheckOnly默认值为false,主要是优化缓存bean,不重复创建bean
(5)处理depend-on依赖实例化:isDependent方法检查该bean是否有循环依赖,如果存在相互先实例化的关系则抛出异常,此处的depend-on属性中是指当前bean实例化之前必须先实例化该属性值中bean,与我们常说的循环依赖是不一样的,该处仅仅是检查该bean必须在另一个bean实例化的前面,可以被注入也可以不被注入;
(6)创建除单例的bean:创建prototype、request或session作用域的bean;
(7)检查返回的bean类型:检查获取bean时是否匹配指定返回的Class类型。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/891994.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-14
下一篇 2022-05-14

发表评论

登录后才能评论

评论列表(0条)

保存