掌握 Spring 必须知道的 BeanDefinition(上)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 什么是 BeanDefinition?BeanDefinition 直译为 bean 定义,描述了一个 bean 实例具有的构造方法参数和属性值等信息。与 Java 中的 Class 类似,Class 是类文件在内存中的表现形式,BeanDefinition 是 Spring Bean 配置元信息在内存中的表现形式,各种配置元信息最后都会被转换为 BeanDefinition ,Spring 根据 BeanDefinition 实例化、初始化 bean,BeanDefinition 涉及到 Spring Bean 的整个生命周期。

什么是 BeanDefinition?


BeanDefinition 直译为 bean 定义,描述了一个 bean 实例具有的构造方法参数和属性值等信息。与 Java 中的 Class 类似,Class 是类文件在内存中的表现形式,BeanDefinition 是 Spring Bean 配置元信息在内存中的表现形式,各种配置元信息最后都会被转换为 BeanDefinition ,Spring 根据 BeanDefinition 实例化、初始化 bean,BeanDefinition 涉及到 Spring Bean 的整个生命周期。


BeanDefinition 的分类及使用场景


在 Spring 3 之前,我们最常用 xml 配置 Spring 中的 bean,Spring 3 及之后,注解逐渐成为使用 Spring 的主要方式。此外较少使用的 bean 配置元数据还包括 properties、groovy,我们甚至可以定义自己的 BeanDefinition。Spring 中的 BeanDefinition 主要如下图所示。


image.png


eanDefinition 是所有 BeanDefinition 实现类的接口,其定义了基本的 BeanDefinition 信息,各实现可以包含其他不同的信息。BeanDefinition 包含的信息及含义如下所示。


image.png


AbstractBeanDefinition 是 BeanDefinition 的抽象实现,并在 BeanDefinition 接口的基础上添加了一些获取 BeanDefinition 其他信息的方法。


RootBeanDefinition 是合并后的 BeanDefinition,由于 BeanDefinition 可以具有父子关系,因此在运行时需要获取最终表示 bean 的 RootBeanDefinition ,其不能再获取父 BeanDefinition。


ChildBeanDefinition ,表示具有 父 BeanDefinition 的 BeanDefinition,使用较少。


GenericBeanDefinition,通用的 BeanDefinition,Spring 推荐编程式注册 BeanDefinition 时使用 GenericBeanDefinition,而不是使用 RootBeanDefinition。


AnnotatedBeanDefinition,注解 BeanDefinition,Spring 注解编程中使用的 BeanDefinition,包含类或方法的注解元信息。


如何创建 BeanDefinition


通常情况下,Spring 在解析不同的配置元信息时会使用不同的 BeanDefinition,我们不必进行关心。而如果我们想通过编程式向 Spring 注册 BeanDefinition ,我们则需要掌握创建 BeanDefinition 的一些技巧。具有两种创建 BeanDefinition 的方式。


直接通过 new 指令创建 BeanDefinition。

通过 BeanDefinitionBuilder 的静态方法创建 BeanDefinition ,这是建造者模式的一种实现,推荐使用这种方式创建 BeanDefinition。示例代码如下所示:


AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(String.class)
        .setLazyInit(true).setAbstract(false).getBeanDefinition();


BeanDefinition 解析


BeanDefinition 通过 BeanDefinitionReader 解析配置元数据获取,BeanDefinitionReader 根据不同的配置元数据具有不同的实现,具体如下。


image.png


根据如上类图,可以发现,除了 BeanDefinitionReader 接口,还具有一个用于解析注解元数据的 AnnotatedBeanDefinitionReader ,这是因为 BeanDefinitionReader 解析的都是资源文件,而 AnnotatedBeanDefinitionReader 是 Spring 3 才添加的用来解析注解元数据为 BeanDefinition。


AbstractBeanDefinitionReader 是 BeanDefinitionReader 的抽象实现,主要将资源位置解析为资源 Resource。 PropertiesBeanDefinitionReader 用来解析 properties 文件,XMLBeanDefinitionReader 用来解析 xml 文件,GrovvyBeanDefinitionReader 用来解析 grovvy 文件。


目前最常用的为注解,在老旧的项目中可能存在 xml 配置文件,而 properties 和 groovy 则几乎没有用户使用。


注解元数据解析


AnnotatedBeanDefinitionReader 解析注解元数据为 BeanDefinition 的核心源码如下。


  private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
      @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
      @Nullable BeanDefinitionCustomizer[] customizers) {
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
    // 先进行 @Conditional 条件评估
    if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
      return;
    }
    abd.setInstanceSupplier(supplier);
    // 解析 scope 信息
    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    abd.setScope(scopeMetadata.getScopeName());
    String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
    // 处理通用的注解信息,如 @Primary、@Lazy 等
    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
    if (qualifiers != null) {
      // 处理 qualifier 信息
      for (Class<? extends Annotation> qualifier : qualifiers) {
        if (Primary.class == qualifier) {
          abd.setPrimary(true);
        }
        else if (Lazy.class == qualifier) {
          abd.setLazyInit(true);
        }
        else {
          abd.addQualifier(new AutowireCandidateQualifier(qualifier));
        }
      }
    }
    // 自定义 BeanDefinition 信息
    if (customizers != null) {
      for (BeanDefinitionCustomizer customizer : customizers) {
        customizer.customize(abd);
      }
    }
    // 创建 BeanDefinition
    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    // 注册 BeanDefinition
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
  }


可以看到,AnnotatedBeanDefinitionReader 实现就是读取类的配置信息,将其转换为对应的 BeanDefinition 属性,然后再创建 BeanDefinition 。需要注意的是,在扫描包时会使用 MetadataReader 读取类,底层使用 asm 读取类,因此不会进行类加载,会将类的元信息抽象为 AnnotationMetadata,此时直接创建 ScannedGenericBeanDefinition 对象。


目录
相关文章
|
5月前
|
XML Java 数据格式
深度解析 Spring 源码:从 BeanDefinition 源码探索 Bean 的本质
深度解析 Spring 源码:从 BeanDefinition 源码探索 Bean 的本质
91 3
|
2月前
|
XML 缓存 Java
spring源码剖析-spring-beans(内部核心组件,BeanDefinition的注册,BeanWapper创建)
spring源码剖析-spring-beans(内部核心组件,BeanDefinition的注册,BeanWapper创建)
49 10
|
2月前
|
XML 存储 Java
spring源码刨析-spring-beans(内部核心组件,beanDefinition加载过程)
spring源码刨析-spring-beans(内部核心组件,beanDefinition加载过程)
|
XML Java 数据格式
我滴妈!人事竟然问我Spring BeanDefinition是如何帮我们解析和加载的?
我滴妈!人事竟然问我Spring BeanDefinition是如何帮我们解析和加载的?
58 0
我滴妈!人事竟然问我Spring BeanDefinition是如何帮我们解析和加载的?
|
XML 存储 设计模式
Spring高手之路11——BeanDefinition解密:构建和管理Spring Beans的基石
本文对BeanDefinition进行全面深入的探讨,涵盖BeanDefinition的接口方法、主要信息、类型以及生成过程等方面内容。旨在帮助读者全面理解BeanDefinition的各方面知识,并能够熟练应用。文章通俗易懂,具有很强的指导意义。
195 0
Spring高手之路11——BeanDefinition解密:构建和管理Spring Beans的基石
|
6月前
|
Java Spring 容器
深入理解BeanDefinition和Spring Beans
本文深入探讨了Spring框架中的BeanDefinition和Spring Beans。BeanDefinition是Bean的元数据,包含类名、作用域、构造函数参数和属性值等信息。Spring Beans是根据BeanDefinition实例化的对象。文章详细阐述了BeanDefinition的属性,如类名、作用域(如单例和原型)及构造函数和属性值。此外,还介绍了如何使用BeanDefinition动态注册、延迟加载和实现依赖注入。通过示例代码,展示了如何创建和自定义BeanDefinition以满足特定需求。理解BeanDefinition有助于更高效地开发和维护Spring应用程序。
106 0
|
XML Java 数据格式
Spring高手之路16——解析XML配置映射为BeanDefinition的源码
本文提供了深入Spring源码的透彻解析,从XML配置文件的加载开始,步入了Spring的内部世界。通过细致剖析setConfigLocations、refresh和loadBeanDefinitions等方法的实现,揭示了Bean从定义到注册的整个生命周期。
139 1
Spring高手之路16——解析XML配置映射为BeanDefinition的源码
|
6月前
|
XML 缓存 Java
Spring5源码(18)-Spring注册BeanDefinition
Spring5源码(18)-Spring注册BeanDefinition
52 0
|
6月前
|
XML 前端开发 Java
【Spring 源码】 深入理解 Bean 定义之 BeanDefinition
【Spring 源码】 深入理解 Bean 定义之 BeanDefinition
|
XML 存储 Java
Spring高手之路12——BeanDefinitionRegistry与BeanDefinition合并解析
本文深入探讨Spring的BeanDefinition和BeanDefinitionRegistry,详细介绍了BeanDefinition的合并过程及其源码分析,揭示了Spring配置元数据的内在逻辑。读者将通过本文理解Spring Bean定义的继承和重用机制,掌握如何动态注册BeanDefinition。
196 0
Spring高手之路12——BeanDefinitionRegistry与BeanDefinition合并解析
下一篇
无影云桌面