全网最细致的spring源码分析(四):spring创建一个bean对象的逻辑和源码解析

        spring最为基础也是极为重要的一个元素单位便是bean,bean由开发者编写的普通java类经过spring按照开发者指定的规则生成而来,作为pojo的替代对象进行使用,之前的学习中已经知道spring通过doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)方法来创建bean实例,简单回顾一下方法里三个参数的作用:

  • beanName:bean的名称,也是bean的标识

  • RootBeanDefinition mbd:一个用来描述bean的对象

  • Object[] args:创建构造函数和工程方法的时候用到的一些参数

为了写出更加出彩、难以发现的bug还需要从源码开始学习。

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
      throws BeanCreationException {
    //初始化这个bean的包装,在bean创建之后会由这个对象来进行包装,对象内部会包含bean的实例和BeanDefinition(用来描述bean的对象)以及一个属性编辑器
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {
        //如果这个bean是单例的,就尝试着从缓存里面获取bean包装对象
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {
        //这里就是创建bean对象的地方,万物起始之处
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
    //获取bean对象
   final Object bean = instanceWrapper.getWrappedInstance();
    //获取bean对象的类型
   Class<?> beanType = instanceWrapper.getWrappedClass();
    //NullBean的意思是内部空的bean
   if (beanType != NullBean.class) {
        //在描述文件中赋值上bean的类型
      mbd.resolvedTargetType = beanType;
   }


   //获取后处理的锁
   synchronized (mbd.postProcessingLock) {
        //是否已经处理过后处理器
      if (!mbd.postProcessed) {
         try {
            //执行合并bean定义的后处理器
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
         }
         catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "Post-processing of merged bean definition failed", ex);
         }
            //修改状态,已经执行过后处理器了,不需要再重复劳动
         mbd.postProcessed = true;
      }
   }


   //判断spring是否应该过早的暴露的bean对象,用来提供对循环依赖的支持。
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
         isSingletonCurrentlyInCreation(beanName));
   if (earlySingletonExposure) {
      if (logger.isTraceEnabled()) {
         logger.trace("Eagerly caching bean '" + beanName +
               "' to allow for resolving potential circular references");
      }
            //注册到单例工程中,getEarlyBeanReference这个方法会将aop动态织入bean中,如果没有aop就直接返回bean
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
   }


   Object exposedObject = bean;
   try {
        //填充bean的属性
      populateBean(beanName, mbd, instanceWrapper);
        //初始化bean
      exposedObject = initializeBean(beanName, exposedObject, mbd);
   }
   catch (Throwable ex) {
      if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
         throw (BeanCreationException) ex;
      }
      else {
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
      }
   }

    //判断是否过早的暴露出去了,就是之前放入缓存的地方
   if (earlySingletonExposure) {
        //从singletonFactories中获取一下
      Object earlySingletonReference = getSingleton(beanName, false);
        //如果获取到了实例,
      if (earlySingletonReference != null) {
            //并且这个实例和初始化之后的bean对象是同一个,就说不是一个代理的bean对象
         if (exposedObject == bean) {
            //把缓存中的bean赋值给exposedObject
            exposedObject = earlySingletonReference;
         }
            //检查依赖这个bean的bean是否都已经初始化好了
         else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
            //获取依赖当前bean的beanname
            String[] dependentBeans = getDependentBeans(beanName);
            Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
            for (String dependentBean : dependentBeans) {
                //检查这些需要依赖的bean,删除掉那些用于类型检测的bean,如果不是的加入到“actualDependentBeans”缓存中
               if (!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 {
        //根据配置的scopse属性,对bean进行注册,如果配置了destroy-method,也需要在这里注册,方便销毁bean的时候调用
      registerDisposableBeanIfNecessary(beanName, bean, mbd);
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
   }
    //返回这个bean
   return exposedObject;
}

        抛开那些烦人的异常处理和日志,回头整理一下这个方法的主要思路:

  1. 如果是单例的bean就先清除掉缓存

  2. 实例bean,将beanDefinition(bean的描述对象)转化成beanWrapper(bean的包装对象)

  3. 执行MergedBeanDefinitionPostProcessor的处理,主要作用就是对@Autowired和@Value注解做预处理。

  4. 解决循环依赖的问题

  5. 对bean的属性进行填充

  6. 检查是否发生循环依赖问题

  7. 注册bean

  8. 返回bean

        方法虽然很长,但是思路清晰,过程简单,当我们了解了循环依赖和spring的解决之道后,这个方法看起来就会很轻松,也能专注于最为重要的一步,就是第二步中的createBeanInstance()方法。

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
   //解析获得bean的class对象
   Class<?> beanClass = resolveBeanClass(mbd, beanName);

    //如果这个beanclass是空的,或者修饰符不是public,或者没有权限访问构造函数和方法,就抛出异常
   if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
            "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
   }

    //初始化supplier,这个对象可以把bean包装成beanWrapper
   Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
   if (instanceSupplier != null) {
      return obtainFromSupplier(instanceSupplier, beanName);
   }

    //如果工厂方法不为空,就根据工厂方法初始化策略
   if (mbd.getFactoryMethodName() != null) {
      return instantiateUsingFactoryMethod(beanName, mbd, args);
   }

    //是否曾经创建过这个bean
   boolean resolved = false;
   boolean autowireNecessary = false;
   if (args == null) {
      synchronized (mbd.constructorArgumentLock) {
            //resolvedConstructorOrFactoryMethod不为空的话,曾经就创建过这个bean
         if (mbd.resolvedConstructorOrFactoryMethod != null) {
            resolved = true;
            //constructorArgumentsResolved为true说明之前采用的是构造函数自动注入的方式
            autowireNecessary = mbd.constructorArgumentsResolved;
         }
      }
   }
    //如果曾经解析过,就使用之前的解析好的构造方法
   if (resolved) {
      if (autowireNecessary) {
        //使用构造函数自动注入
         return autowireConstructor(beanName, mbd, null, null);
      }
      else {
        //使用默认的构造函数
         return instantiateBean(beanName, mbd);
      }
   }


   // 走到这里说明是第一次创建bean,获取构造函数
   Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
   if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
         mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
        //构造函数的方式进行加载
      return autowireConstructor(beanName, mbd, ctors, args);
   }


   //如果设置了指定的构造函数,就是用这个构造函数进行加载
   ctors = mbd.getPreferredConstructors();
   if (ctors != null) {
      return autowireConstructor(beanName, mbd, ctors, null);
   }

   // 直接初始化bean
   return instantiateBean(beanName, mbd);
}

        spring实例化bean的细节还是相当复杂的,spring将逻辑提取到createBeanInstance()方法中,将具体实现封装到autowireConstructor()和instantiateBean()的方法中。

  1. 查看BeanDefinition中指定了Supplier或者指定了工厂方法,就直接从这里跳过去,并且返回结果。

  2. 解析构造函数,并通过构造函数进行实例化。一个类可能有多个构造函数,每个构造函数的参数不同,spring根据参数数量和类型判断最终使用哪个构造函数进行实例化。但是判断的过程是个比较消耗性能的步骤,spring采用了一个缓存的机制,减少重复的解析。

 

    autowireConstructor()和instantiateBean()两个方法的冗长又极为复杂,让人难以理解又昏昏欲睡,所以我们还是留到下一次再讲,我先睡一会(¦3[▓▓]    果然看源码是最好的安眠药。。。。

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值