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

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



目录
相关文章
|
5天前
|
XML Java 数据格式
【SpringFramework】Spring IoC-基于XML的实现
本文主要讲解SpringFramework中IoC和DI相关概念,及基于XML的实现方式。
96 69
|
3天前
|
Java Spring 容器
【SpringFramework】Spring IoC-基于注解的实现
本文主要记录基于Spring注解实现IoC容器和DI相关知识。
36 21
|
10天前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
8天前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
|
8天前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
|
3月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
254 2
|
10天前
|
Java 数据库连接 Maven
最新版 | 深入剖析SpringBoot3源码——分析自动装配原理(面试常考)
自动装配是现在面试中常考的一道面试题。本文基于最新的 SpringBoot 3.3.3 版本的源码来分析自动装配的原理,并在文未说明了SpringBoot2和SpringBoot3的自动装配源码中区别,以及面试回答的拿分核心话术。
最新版 | 深入剖析SpringBoot3源码——分析自动装配原理(面试常考)
|
17天前
|
NoSQL Java Redis
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
67 14
|
2月前
|
缓存 IDE Java
SpringBoot入门(7)- 配置热部署devtools工具
SpringBoot入门(7)- 配置热部署devtools工具
56 1
SpringBoot入门(7)- 配置热部署devtools工具
|
2月前
|
缓存 IDE Java
SpringBoot入门(7)- 配置热部署devtools工具
SpringBoot入门(7)- 配置热部署devtools工具
55 2
 SpringBoot入门(7)- 配置热部署devtools工具