软件编程
位置:首页>> 软件编程>> java编程>> SpringIOC BeanDefinition的加载流程详解

SpringIOC BeanDefinition的加载流程详解

作者:AntBlack  发布时间:2023-11-25 18:06:22 

标签:SpringIOC,BeanDefinition,加载

一.前言

这一篇来看看 SpringIOC 里面的一个细节点 , 来简单看看 BeanDefinition 这个对象 , 以及有没有办法对其进行定制.

CASE 备份 : 👉 gitee.com/antblack/ca…

二. BeanDefinition 的体系

2.1 体系概览

SpringIOC BeanDefinition的加载流程详解

这里面需要关注的几个类分别为 :

  • BeanDefinition 接口 : 顶层接口 , 抽象了Bean加载的方法

  • AbstractBeanDefinition : 提供了多数方法的默认实现

  • RootBeanDefinition : Spring BeanFactory 运行时统一的 BeanDefinition 视图

  • GenericBeanDefinition : 编程方式注册 BeanDefinition 的首选类

  • ChildBeanDefinition : 可继承BeanDefinition

下面来解释一下这里面说的一些概念 :

什么叫统一视图 ?

稍微从跟踪一下源码就能发现 , 从 xml 或者 JavaConfig 以及 Spring 默认加载的Bean配置类 ,最终都会被修饰为 RootBeanDefinition

GenericBeanDefinition 怎么用 ?

GenericBeanDefinition 是通过编程方式注入的 BeanDefinition 所对应的类 ,通常都是该类的子类 , 包括非Spring 的 ConfigBean 和 ServiceBean

ChildBeanDefinition 又做了什么 ?

一种可以继承 parent 配置的 BeanDefinition , 在加载环节中会通过 AbstractBeanFactory#getMergedLocalBeanDefinition() 来将 child 和 parent bean definition 进行合并。

  • BeanDefinition 进行 merge 操作时,会将 child 的属性与 parent 的属性进行合并,当有相同属性时,以 child 的为准

  • 如果是 Map 形式的配置 , 会取并集

2.2 BeanDefinition 的作用

  • 存储属性 : 基于接口 AttributeAccessor 实现

  • 存储元数据配置 : 基于 BeanMetadataElement 实现

  • 描述类的信息 : 包括Bean名称 , Primary 属性 , priority 配置 等等

  • Bean 的加载 : 例如 getBeansOfType , getBean 等等

总结其实就是一句话 : BeanDefinition 主要承载了Bean的元数据信息 ,同时描述了Bean在Spring体系中的加载方式 , 容器通过 BeanDefinition 中的配置来加载一个Bean

三. BeanDefinition 的载入

3.1 载入的入口

S1 : 启动配置类的载入

Spring 中第一个载入的 BeanDefinition 即为 RootBeanDefinition , 主要通过 AnnotationConfigUtils # registerAnnotationConfigProcessors 方法进行加载

在这个环节中会通过加载的方式分别载入多个不同的 RootBeanDefinition , 这里是 Contain 关系 :

// internalConfigurationAnnotationProcessor
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
  // 构建对应的 PostProcessor 并且载入
  RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
  def.setSource(source);
  beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// internalAutowiredAnnotationProcessor
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
   //.....
}

在这个环节中 , 基本上都是在通过 registerPostProcessor 来注册各类加载类 , 我把这些看成根类 .

这些类通常为 Spring 进行服务 , 用来配置各类信息和加载封装 Bean

S2 : 普通配置类的载入

普通类的载入包括 SpringApplication 和一些自定义的个人配置类 , 这些类主要为了对非 Spring 的组件进行注册 , 配置 , 注入等操作

这一类通常通过 registerBean 来实现Bean的注册 , 注册的入口也很多 :

包括 AnnotatedBeanDefinitionReaderConfigurationClassPostProcessor等, 不难发现这一类 BeanDefinition 通常都是由 RootBeanDefinition 装载的类进行载入的

通常注册出来的对象也为 AnnotatedGenericBeanDefinition 和 GenericBeanDefinition 的子类等

3.2 保存的逻辑

BeanDefinition 会在 DefaultListableBeanFactory # registerBeanDefinition 中进行注册.

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
     throws BeanDefinitionStoreException {
  // S1 : 会对 BeanDefinition 进行校验 , 主要是MethodOverrides和FactoryMethodName不能同时存在
  // -- 工厂方法必须创建具体的 Bean 实例 , 而 methodOverrides 会创建代理类且进行增强
  // -- 也就是说 工厂需要实例 , 不能是代理类
  if (beanDefinition instanceof AbstractBeanDefinition) {
      ((AbstractBeanDefinition) beanDefinition).validate();
  }
  // S2 : 判断 BeanDefinition 是否已经存在
  BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
  if (existingDefinition != null) {
     // 是否允许同名Bean重写 , 因为此处已经存在一个了 , 不能重写则直接异常
     if (!isAllowBeanDefinitionOverriding()) {
        throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
     }else if (existingDefinition.getRole() < beanDefinition.getRole()) {
         // 角色比较 ,只打日志
         // ROLE_APPLICATION / ROLE_SUPPORT / ROLE_INFRASTRUCTURE
     }else if (!beanDefinition.equals(existingDefinition)) {
         // 判断是否为同一对象
     }
     // 以上主要是打log , 这里如果允许覆盖则直接覆盖了
     this.beanDefinitionMap.put(beanName, beanDefinition);
  }
  else {
     // 判断该Bean是否已经开始初始化
     if (hasBeanCreationStarted()) {
        // 如果已经开始 , 需要对 Map 上锁后再处理
        synchronized (this.beanDefinitionMap) {
           this.beanDefinitionMap.put(beanName, beanDefinition);
           // 省略一些更新操作
        }
     }
     else {
        // 没有加载时的载入
        this.beanDefinitionMap.put(beanName, beanDefinition);
        this.beanDefinitionNames.add(beanName);
        removeManualSingletonName(beanName);
     }
     this.frozenBeanDefinitionNames = null;
  }
  // 如果Bean已经存在或已经开始加载了 , 这个时候时需要进行销毁操作的
  if (existingDefinition != null || containsSingleton(beanName)) {
     resetBeanDefinition(beanName);
  }
}
protected void resetBeanDefinition(String beanName) {
  // S1 : 如果已经创建 ,需要清空 Merge BeanDefinition
  clearMergedBeanDefinition(beanName);
  // S2 : 销毁 Bean
  destroySingleton(beanName);
  // S3 : 调用 PostProcessors 重置处理器进行处理
  for (BeanPostProcessor processor : getBeanPostProcessors()) {
     if (processor instanceof MergedBeanDefinitionPostProcessor) {
        ((MergedBeanDefinitionPostProcessor) processor).resetBeanDefinition(beanName);
     }
  }
  // S4 : 如果该 BeanDefinition 是某个BeanDefinition 的Parent , 则需要同步处理
  for (String bdName : this.beanDefinitionNames) {
     if (!beanName.equals(bdName)) {
        BeanDefinition bd = this.beanDefinitionMap.get(bdName);
        if (bd != null && beanName.equals(bd.getParentName())) {
           resetBeanDefinition(bdName);
        }
     }
  }
}

3.3 使用的方式

BeanDefinition 的批量处理流程也是在 DefaultListableBeanFactory 中进行的

public void preInstantiateSingletons() throws BeansException {
  List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
  // 对所有的 BeanDefinition 进行循环处理
  for (String beanName : beanNames) {
     RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
     // 排除掉懒加载的Bean
     if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
        // 此处省略工厂类的判断及处理 ...
        // 进入Bean获取逻辑
        getBean(beanName);
     }
  }
   //.....
}

来源:https://juejin.cn/post/7157695463415087140

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com