深入理解Spring IOC(六)、 bean的填充以及初始化工作(上)

简介: 深入理解Spring IOC(六)、 bean的填充以及初始化工作(上)

如果你已经看到了这里并且把之前的都看明白了,那么恭喜你,最难的地方你已经搞定了。现在在整个spring ioc的流程中,对你来说应该不会再有太难的了,同时再去看spring的其他模块的源码,也相对会容易一些,尤其是其他框架和Spring整合的代码。如果没有看懂的也别着急,你可以把本篇看完,然后回过头去再去看之前的,源码也很少有人一遍就能看明白,我自己看这块的源码也是看了很多遍以及debug了很多遍才明白的。

!

复制代码

真的需要你的一个赞来鼓励一下,因为写这种源码解析真的太太太太不容易了😢,谁写谁知道。

回到正题,我们上一篇主要说了doCreateBean中的createBeaninstance这个方法,这个方法为我们创建了未被填充的bean实例,本篇我们来看已经创建出来的bean实例是怎样被填充以及初始化的。

我们回到doCreateBean方法中,我再把这个方法代码贴一下,其中,1处上篇已经讲过,我们直接来看第2处

typescript

复制代码

代码块1
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
  // BeanWrapper是bean的包装类
  BeanWrapper instanceWrapper = null;
  if (mbd.isSingleton()) {
    // 从正在创建的factoryBean的缓存中移除(准确说其实是去拿,同时移除)
    instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
  }
  if (instanceWrapper == null) {
    // 1. 如果到这里是null,则去创建一个包含着bean实例的instanceWrapper
    instanceWrapper = createBeanInstance(beanName, mbd, args);
  }
  final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
  Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
  // 使用MergedBeanDefinitionPostProcessor修改RootBeanDefinition
  // 主要是处理@Autowired 、 @inject 、@value 标着的方法和属性
  // 从这里往后,spring 才知道是哪个方法或者是属性有这个注解
  // 这里的具体的代码解析不再贴出来(因为不是重点),在我第一篇的github上面你也可以自己下载源码来看,里面都有注释
  synchronized (mbd.postProcessingLock) {
    if (!mbd.postProcessed) {
      applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
      mbd.postProcessed = true;
    }
  }
  // earlySingletonExposure是判断是否要提前曝光这个半成品的实例的,注意哈:现在的bean只是个半成品
  // 因为还没有进行属性填充,以及执行初始化方法等操作
  // mbd是单例 && 允许循环引用(默认true) && 当前bean是不是正在创建中
  boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
      isSingletonCurrentlyInCreation(beanName));
  if (earlySingletonExposure) {
    if (logger.isDebugEnabled()) {
      logger.debug("Eagerly caching bean '" + beanName +
          "' to allow for resolving potential circular references");
    }
    // 提前曝光这个beanName对应的ObjectFactory,用来解决循环引用
    addSingletonFactory(beanName, new ObjectFactory<Object>() {
      @Override
      public Object getObject() throws BeansException {
        // 2.使用SmartInstantiationAwareBeanPostProcessor返回早期bean的半成品时的引用
        // 如果没有SmartInstantiationAwareBeanPostProcessor,则直接返回bean
        // 这里返回的最终是bean本身
        return getEarlyBeanReference(beanName, mbd, bean);
      }
    });
  }
  // 初始化
  Object exposedObject = bean;
  try {
    // 3. 对bean进行属性填充
    populateBean(beanName, mbd, instanceWrapper);
    if (exposedObject != null) {
      // 4. 初始化操作
      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);
    }
  }
  // 如果需要提前曝光半成品bean
  if (earlySingletonExposure) {
    Object earlySingletonReference = getSingleton(beanName, false);
    if (earlySingletonReference != null) {
      if (exposedObject == bean) {
        // 由于经过init之后的操作,earlySingletonReference和exposedObject可能不是一个实例,
        // 这里需要让他们指向一个实例,
        exposedObject = earlySingletonReference;
      // 不允许在循环依赖情况下注入原始bean && 当前bean被其他bean依赖
      }else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
        // 拿到当前bean依赖所有bean的数组
        String[] dependentBeans = getDependentBeans(beanName);
        Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
        for (String dependentBean : dependentBeans) {
          // 移除这些bean,因为这些bean依赖的bean是被增强过的bean
          if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
            // 移除失败的添加到actualDependentBeans
            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 {
    // 注册用于销毁的bean,
    registerDisposableBeanIfNecessary(beanName, bean, mbd);
  }catch (BeanDefinitionValidationException ex) {
    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
  }
  return exposedObject;
}

代码块1中2处


代码块2
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
  Object exposedObject = bean;
  // bean不是null && mbd不是合成 && 有InstantiationAwareBeanPostProcessor
  if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    // 遍历执行BeanPostProcessor
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
      if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
        SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
        // 具体的处理逻辑位于AutowiredAnnotationBeanPostProcessor中,它继承了这个方法,最终返回的还是是bean本身,
        // 注意:如果有别的实现了SmartInstantiationAwareBeanPostProcessor就未必了
        exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
        if (exposedObject == null) {
          return exposedObject;
        }
      }
    }
  }
  return exposedObject;
}


此时我相信这里你肯定是可以看明白的


代码块1中3处


这个populateBean方法,即是处理属性注入的地方,@Autowired,@Resource,@Value,甚至是当你使用Dubbo框架的时候@Reference都是在这里处理注入的,我们一起看看这个方法:


代码块3
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
  PropertyValues pvs = mbd.getPropertyValues();
  // 进行基本的校验,bw为null时
  if (bw == null) {
    // 如果有属性值,则抛异常
    if (!pvs.isEmpty()) {
      throw new BeanCreationException(
          mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
    // 否则 结束方法
    }else {
      return;
    }
  }
  // 是否继续填充属性的标记
  boolean continueWithPropertyPopulation = true;
  // mbd是否为合成 && 是否存在InstantiationAwareBeanPostProcessor
  if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
      if (bp instanceof InstantiationAwareBeanPostProcessor) {
        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
        // postProcessAfterInstantiation这个方法是在bean实例化后属性填充之前调用
        // 返回的是true,说明应该进行属性填充,false说明不应该
        if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
          continueWithPropertyPopulation = false;
          break;
        }
      }
    }
  }
  // 如果不该继续填充了则直接返回
  if (!continueWithPropertyPopulation) {
    return;
  }
  // 这个是处理xml中autowire的值为byname 和 byType的逻辑
  // 可以看出来只有xml的才会走这里,注解的没有byName 和 byType这样的属性
  if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
      mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
    MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
    // 1.byName的处理
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
      autowireByName(beanName, mbd, bw, newPvs);
    }
    // 2.byType的处理
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
      autowireByType(beanName, mbd, bw, newPvs);
    }
    pvs = newPvs;
  }
  // 是否有InstantiationAwareBeanPostProcessors
  boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
  // 是否需要依赖检查
  boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
  if (hasInstAwareBpps || needsDepCheck) {
    PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
    if (hasInstAwareBpps) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
          // 用InstantiationAwareBeanPostProcessor的后置处理来进行属性的填充
          // 这里进行的是属性填充前最后一步的处理,@AutoWired就是在这里进行处理的
          // 也就是说这里会对@Autowired的属性进行初始化,然后加到pvs中来
          // 当然,@Resource也是在这里处理的,只是用的BeanPostProcessor不是一个
          // 注:@Autowired的处理逻辑在AutowiredAnnotationBeanPostProcessor中,而
          // @Resource的在CommonAnnotationBeanPostProcessor里
          InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
          pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
          if (pvs == null) {
            return;
          }
        }
      }
    }
    if (needsDepCheck) {
      // 对filteredPds里面的属性进行依赖检查
      checkDependencies(beanName, mbd, filteredPds, pvs);
    }
  }
  // 3.进行填充操作
  applyPropertyValues(beanName, mbd, bw, pvs);
}


这个代码块中的1、2个,是针对xml中bean标签的autowire属性的,虽然现在用的很少了,但是本着完整的原则,还是来看看它:


代码块3中1处


代码块4
protected void autowireByName(
      String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
  // 获取需要注入的属性的名称
  String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
  for (String propertyName : propertyNames) {
    // 如果现在beanFactory容器中有这个propertyName对应的bean或者是
    // 对应的beanDefinition
    if (containsBean(propertyName)) {
      // 则去初始化这个bean
      Object bean = getBean(propertyName);
      // 将所依赖的bean加入pvs容器中以备后续使用
      pvs.add(propertyName, bean);
      // 注册依赖关系
      registerDependentBean(propertyName, beanName);
      if (logger.isDebugEnabled()) {
        logger.debug("Added autowiring by name from bean name '" + beanName +
            "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
      }
    }
    else {
      if (logger.isTraceEnabled()) {
        logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
            "' by name: no matching bean found");
      }
    }
  }
}


代码块3中2处


代码块5
protected void autowireByType(
      String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
  // 拿自定义的TypeConverter,如果为空,则用bw做TypeConverter
  TypeConverter converter = getCustomTypeConverter();
  if (converter == null) {
    converter = bw;
  }
  Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);
  // 拿到需要注入的属性的名称
  String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
  for (String propertyName : propertyNames) {
    try {
      // 拿到bw的对应这个propertyName的PropertyDescriptor
      PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
      // 如果pd是个Object类型的,则不注入这个。原因是如果是Object,你找到的参数即使类型不匹配
      // 也能注入成功。。
      if (!Object.class.equals(pd.getPropertyType())) {
        MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
        // Do not allow eager init for type matching in case of a prioritized post-processor.
        boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
        DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
        // 真正的解析过程
        Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
        // 把解析成功的参数放到pvs里
        if (autowiredArgument != null) {
          pvs.add(propertyName, autowiredArgument);
        }
        for (String autowiredBeanName : autowiredBeanNames) {
          registerDependentBean(autowiredBeanName, beanName);
          if (logger.isDebugEnabled()) {
            logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
                propertyName + "' to bean named '" + autowiredBeanName + "'");
          }
        }
        autowiredBeanNames.clear();
      }
    }
    catch (BeansException ex) {
      throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
    }
  }
}



目录
相关文章
|
11天前
|
Java 测试技术 开发者
Spring IoC容器通过依赖注入机制实现控制反转
【4月更文挑战第30天】Spring IoC容器通过依赖注入机制实现控制反转
21 0
|
10天前
|
安全 Java 开发者
在Spring框架中,IoC和AOP是如何实现的?
【4月更文挑战第30天】在Spring框架中,IoC和AOP是如何实现的?
21 0
|
11天前
|
XML Java 程序员
什么是Spring的IoC容器?
【4月更文挑战第30天】什么是Spring的IoC容器?
19 0
|
11天前
|
消息中间件 安全 Java
在Spring Bean中,如何通过Java配置类定义Bean?
【4月更文挑战第30天】在Spring Bean中,如何通过Java配置类定义Bean?
19 1
|
12天前
|
消息中间件 安全 Java
探索|Spring并行初始化加速的思路和实践
作者通过看过的两篇文章发现实现Spring初始化加速的思路和方案有很多类似之处,通过本文记录一下当时的思考和实践。
|
13天前
|
前端开发 Java 数据格式
【Spring系列笔记】定义Bean的方式
在Spring Boot应用程序中,定义Bean是非常常见的操作,它是构建应用程序的基础。Spring Boot提供了多种方式来定义Bean,每种方式都有其适用的场景和优势。
31 2
|
13天前
|
Java Spring 容器
【Spring系列笔记】IOC与DI
IoC 和 DI 是面向对象编程中的两个相关概念,它们主要用于解决程序中的依赖管理和解耦问题。 控制反转是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入和依赖查找。
30 2
|
14天前
|
Java 测试技术 数据库连接
Spring中ioc的优点
总之,Spring中的IoC提供了一种更加灵活、可维护、可测试和可扩展的方式来管理组件之间的依赖关系,从而提高了应用程序的质量和可维护性。这使得开发人员能够更专注于业务逻辑而不是底层的技术细节。
32 1
|
15天前
|
XML 人工智能 Java
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
|
2月前
|
Java 应用服务中间件 Maven
SpringBoot 项目瘦身指南
SpringBoot 项目瘦身指南
53 0