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

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 深入理解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);
    }
  }
}



目录
相关文章
|
7天前
|
XML Java 数据格式
【SpringFramework】Spring IoC-基于XML的实现
本文主要讲解SpringFramework中IoC和DI相关概念,及基于XML的实现方式。
97 69
|
5天前
|
Java Spring 容器
【SpringFramework】Spring IoC-基于注解的实现
本文主要记录基于Spring注解实现IoC容器和DI相关知识。
40 21
|
12天前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
10天前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
|
10天前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
|
5月前
|
XML Java 数据格式
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
这篇文章是Spring5框架的实战教程,主要介绍了如何在Spring的IOC容器中通过XML配置方式使用外部属性文件来管理Bean,特别是数据库连接池的配置。文章详细讲解了创建属性文件、引入属性文件到Spring配置、以及如何使用属性占位符来引用属性文件中的值。
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
|
7月前
|
XML Java 数据格式
Spring5系列学习文章分享---第一篇(概述+特点+IOC原理+IOC并操作之bean的XML管理操作)
Spring5系列学习文章分享---第一篇(概述+特点+IOC原理+IOC并操作之bean的XML管理操作)
54 1
|
4月前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
285 18
|
7月前
|
XML druid Java
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
76 0
|
5月前
|
XML Java 数据格式
Spring5入门到实战------3、IOC容器-Bean管理XML方式(一)
这篇文章详细介绍了Spring框架中IOC容器的Bean管理,特别是基于XML配置方式的实现。文章涵盖了Bean的定义、属性注入、使用set方法和构造函数注入,以及如何注入不同类型的属性,包括null值、特殊字符和外部bean。此外,还探讨了内部bean的概念及其与外部bean的比较,并提供了相应的示例代码和测试结果。
Spring5入门到实战------3、IOC容器-Bean管理XML方式(一)