前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot源码学习(十一) - bean的实例化过程

SpringBoot源码学习(十一) - bean的实例化过程

作者头像
写一点笔记
发布2020-10-10 10:59:51
7850
发布2020-10-10 10:59:51
举报
文章被收录于专栏:程序员备忘录程序员备忘录

上一篇文章中我们解释了Spring对于类级别的注解的解析过程,通过类级别的注解spring基本是将所有该加载的类都加载到待解析的BeanDefineMap中去了。但是BeanDefineMap可不是实例化的bean哦,可以说通过类级别的注解之后Spring还是一个粗糙的商品,但是要变成一个精美的可以使用的Bean还需要将这个粗糙的商品进行一番美化。那么这个美化的动作就是content.getBean()方法了。考虑到类的实例化过程可能会依赖其他的bean还有一些类内部的注解比如@Autowired、@Queries等都需要考虑。所以说getBean是比较复杂的。之前通过源码查看的时候稍微看到了这块,感到压力很大。但是有时候确实让人迫不得已的要去做这件事。因为我们还没有解释@Autowired是如何注入的问题。所以就让我们通过这期的学习解答这个问题吧!

在之前我们说上述代码就是实例化bean的代码。这块我们主要看一下

beanFactory.preInstantiateSingletons();方法

代码语言:javascript
复制
  @Override
  public void preInstantiateSingletons() throws BeansException {
    if (logger.isTraceEnabled()) {
      logger.trace("Pre-instantiating singletons in " + this);
    }
//拿到所有注册的bean的名称
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    //遍历
    for (String beanName : beanNames) {
    //拿到粗糙的bean
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
        //判断是否为工厂bean
        if (isFactoryBean(beanName)) {
        //给beanName+前缀 & 符号
          Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
          if (bean instanceof FactoryBean) {
          //如果是工厂bean
            final 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());
            }
            //调用正在的getBean
            if (isEagerInit) {
              getBean(beanName);
            }
          }
        }
        else {
        //非工厂bean
          getBean(beanName);
        }
      }
    }

    // 通过上述方法就将bean注册进去了。这里迭代做一些处理
    for (String beanName : beanNames) {
    //拿到单例bean
      Object singletonInstance = getSingleton(beanName);
      if (singletonInstance instanceof SmartInitializingSingleton) {
        //判断当前的bean是否实现了SmartInitializingSingleton接口
        final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
        if (System.getSecurityManager() != null) {
          AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            smartSingleton.afterSingletonsInstantiated();
            return null;
          }, getAccessControlContext());
        }
        else {
        //做一些后置处理
          smartSingleton.afterSingletonsInstantiated();
        }
      }
    }
  }

通过上边的分析,我们知道getBean是很重要的方法。那么这块做了哪些工作?

我们看到这里的doGetBean方法,说明这里是正真搞事情的地方。毫无疑问,伟大的目标必将付出艰苦的努力。这块的代码很长!

代码语言:javascript
复制
  protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
      @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

//先把传入的名称进行转化。因为可能传入的是别名什么的,所以要处理一下,如果之前都添加了前缀
    final String beanName = transformedBeanName(name);
    Object bean;
    // 先尝试从缓存中加载bean,如果不存在会调用getBean方法,因为创建单例bean的时候存在循环依赖的问题
    //Spring创建bean的时候是不等bean创建结束就将bean的ObjectFactory提早曝光。就是将ObjectFactory加入到缓存。
    //一旦下一个bean创建的时候需要依赖上一个bean的时候则可以直接使用
    //从缓存或者singleFactories中的ObjectFactory中获取。
    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 + "'");
        }
      }
  /**
     * 如果sharedInstance是普通的单例bean,下面的方法会直接返回。但如果
     * sharedInstance是FactoryBean类型的,则需调用getObject工厂方法获取真正的
     * bean实例。如果用户想获取 FactoryBean 本身,这里也不会做特别的处理,直接返回
     * 即可。毕竟 FactoryBean 的实现类本身也是一种 bean,只不过具有一点特殊的功能而已。
     */
     //有时候BeanFactory返回的并不是实例本身而是指定方法返回的实例
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }
    else {
//Spring只能解决单例对象的setter注入的循环依赖,不能解决构造器注入,
//也不能解决多实例的循环依赖
      if (isPrototypeCurrentlyInCreation(beanName)) {
        throw new BeanCurrentlyInCreationException(beanName);
      }
//如果已经加载的类没有当前类就从parentBeanFactory中加载。
      BeanFactory parentBeanFactory = getParentBeanFactory();
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
   //若存在父工厂,切当前的bean工厂不存在当前的bean定义,
   //那么bean定义是存在于父beanFactory中
   //获取原始名称
        String nameToLookup = originalBeanName(name);
        if (parentBeanFactory instanceof AbstractBeanFactory) {
          return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
              nameToLookup, requiredType, args, typeCheckOnly);
        }
        else if (args != null) {
          //委托给构造函数
          return (T) parentBeanFactory.getBean(nameToLookup, args);
        }
        else if (requiredType != null) {
          // 没有args,委托给标准的getBean()处理
          return parentBeanFactory.getBean(nameToLookup, requiredType);
        }
        else {
        //使用父工厂创建bean
          return (T) parentBeanFactory.getBean(nameToLookup);
        }
      }
/**
 * 方法参数typeCheckOnly ,是用来判断调用getBean(...) 方法时,表示是否为仅仅进行类型检查获取Bean对象
 * 如果不是仅仅做类型检查,而是创建Bean对象,则需要调用markBeanAsCreated(String beanName) 方法,进行记录
 */
      if (!typeCheckOnly) {
        markBeanAsCreated(beanName);
      }
      try {
       //从容器中获取beanName相应的GenericBeanDefinition对象,并将其转换为RootBeanDefinition对象
        final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         //检查当前创建的bean定义是不是抽象的bean定义
        checkMergedBeanDefinition(mbd, beanName, args);

      //处理dependsOn的依赖(这个不是我们所谓的循环依赖 而是bean创建前后的依赖)
       //依赖bean的名称
        String[] dependsOn = mbd.getDependsOn();
        if (dependsOn != null) {
         
          for (String dep : dependsOn) {
          //beanName是当前正在创建的bean,dep是正在创建的bean的依赖的bean的名称
            if (isDependent(beanName, dep)) {
              throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
            }
            //保存的是依赖beanName之间的映射关系:
            //依赖beanName -> beanName的集合
            registerDependentBean(dep, beanName);
            try {
            //获取dependsOn的bean
              getBean(dep);
            }
            catch (NoSuchBeanDefinitionException ex) {
              throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
            }
          }
        }

    //是单例则创建单例Bean
        if (mbd.isSingleton()) {
          sharedInstance = getSingleton(beanName, () -> {
            try {
            //这里是重点
              return createBean(beanName, mbd, args);
            }
            catch (BeansException ex) {
             //清除旧信息
              destroySingleton(beanName);
              throw ex;
            }
          });
          bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
        }

        else if (mbd.isPrototype()) {
          // 如果是一个属性,就创建
          Object prototypeInstance = null;
          try {
            beforePrototypeCreation(beanName);
            prototypeInstance = createBean(beanName, mbd, args);
          }
          finally {
            afterPrototypeCreation(beanName);
          }
          bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
        }

        else {
        //指定scope上实例化bean
          String scopeName = mbd.getScope();
          final 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);
              }
            });
            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;
      }
    }
    //一些检测
    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;
  }

通过上述代码查看,我们大概描述一下getBean的过程,首先对bean的名称做一些处理,之前的bean名称都是添加工厂名称的。所以要处理一下。处理完之后先从缓存中获取bean,同时将该bean对应的ObjectFactory加入到缓存中,同时如果从缓存中获取到之后就进行对Bean进行判断,看是否为工厂Bean,如果是工厂bean就需要返回对应方法的返回结果。判断完毕之后就对bean的属性进行初始化了,如果是单例就处理单例,如果是property就相应做处理。当然还有对scope做处理的。我们一般都是单例吧。当然如果没有从工厂中获取到bean的话就尝试从父工厂中获取。

那么我们看一下createBean方法都做了哪些事情

代码语言:javascript
复制
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {
    if (logger.isTraceEnabled()) {
      logger.trace("Creating instance of bean '" + beanName + "'");
    }
    RootBeanDefinition mbdToUse = mbd;
//解析class
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
    }
    // 验证以及准备覆盖方法
    try {
      mbdToUse.prepareMethodOverrides();
    }
    catch (BeanDefinitionValidationException ex) {
      throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
          beanName, "Validation of method overrides failed", ex);
    }
    try {
      // 给BeanPostProcessors一个机会来替换原来的bean
      //该方法里有两个接口可以对bean进行处理
      //instantiationAwareBeanPostProcessor
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      if (bean != null) {
      //返回
        return bean;
      }
    }
    catch (Throwable ex) {
      throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
          "BeanPostProcessor before instantiation of bean failed", ex);
    }
    try {
    //如果BeanPostProcessors没有做处理就自己创建
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
      if (logger.isTraceEnabled()) {
        logger.trace("Finished creating instance of bean '" + beanName + "'");
      }
      return beanInstance;
    }
    catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {

      throw ex;
    }
    catch (Throwable ex) {
      throw new BeanCreationException(
          mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    }
  }
代码语言:javascript
复制
//这里才是真正创建bean的地方
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
        //从缓存中移除
            instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
        //创建
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }
        Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }
//这里处理类内注解,通过查看我们发现主要有图所示的处理类。这些类是爱注册beanpostprocessors中加入的
        synchronized(mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                //处理的过程
                    this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                } catch (Throwable var17) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
                }
                mbd.postProcessed = true;
            }
        }
        //是否提前曝光
        boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
        if (earlySingletonExposure) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
            }
            this.addSingletonFactory(beanName, () -> {
                return this.getEarlyBeanReference(beanName, mbd, bean);
            });
        }
        Object exposedObject = bean;
        try {
        //对bean进行填充
            this.populateBean(beanName, mbd, instanceWrapper);
            //这块是实例化bean调用后置处理器的部分exposedObject就是bean实体
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);
        } catch (Throwable var18) {
            if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
                throw (BeanCreationException)var18;
            }
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
        }
        if (earlySingletonExposure) {
            Object earlySingletonReference = this.getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
                    String[] dependentBeans = this.getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                    String[] var12 = dependentBeans;
                    int var13 = dependentBeans.length;
                    for(int var14 = 0; var14 < var13; ++var14) {
                        String dependentBean = var12[var14];
                        if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }
                    if (!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }
        try {
            this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
            return exposedObject;
        } catch (BeanDefinitionValidationException var16) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
        }
    }

大概看源码发现doCreateBean才是主要的创建Bean的地方,主要的操作就是对类内部注解进行解析,然后解析完毕之后会统一调initializeBean方法。initalizeBean就开始执行Aware、前置处理器、初始化方法、后置处理器等顺序进行执行,通过这些方法后类才真正的实例化并注册到IOC中。至于initalizeBean没有什么可说的,都是常规操作。但是我们需要记住的是它调用的过程,首先是一波Aware接口的调用,之后是BeanPostProfrosses的前置处理器,然后是Bean的初始化方法,最后是BeanPostProcessors的后置处理方法。而且这个InitalizeBean的方法是只要调用了getBean都会执行。所有保证了InitalizeBean里边的方法都可以执行到到。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-09-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员备忘录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档