Spring 源码学习 05:BeanDefinition 概念及其实现

2020-12-07 11:49:52 浏览数 (1)

前言

BeanDefinition:顾名思义,就是 Bean 的定义,是用来描述一个 Bean 都有什么信息。前面说在初始化 DefaultListableBeanFactory 时,会初始化一个 Map<String, BeanDefinition>,这个 Map 的功能暂且不说,(PS:查资料说的是存储 bean),所以今天就结合官方文档以及源码,一起了解一下 BeanDefinition

1

概念

在容器内部,使用 BeanDefinition 对象定义一个 Bean。而定义的信息包含 类名、作用域、是否懒加载、构造参数、初始化方法、销毁方式等等。

了解了概念之后,开始阅读源码,源码部分比较长。

2

源码

BeanDefinition

通过 UML 可以看出 BeanDefinition 接口继承了 AttributeAccessor 和 BeanMetadataElement 两个接口。

AttributeAccessor

AttributeAccessor:定义用于将元数据附加到任意对象或从任意对象访问元数据的通用协定的接口。

代码语言:javascript复制
public interface AttributeAccessor {

    void setAttribute(String name, @Nullable Object value);

    @Nullable
    Object getAttribute(String name);

    @Nullable
    Object removeAttribute(String name);

    boolean hasAttribute(String name);

    String[] attributeNames();
}

通过接口方法可以看出,AttributeAccessor 主要定义了对元数据属性的增删改查。

AttributeAccessorSupport 是 AttributeAccessor 接口的一个实现,通过实现可以看出,其内部使用了 Map 保存名称和属性值。

BeanMetadataElement

BeanMetadataElement:由包含配置源对象的 bean 元数据元素实现的接口。

代码语言:javascript复制
public interface BeanMetadataElement {
    @Nullable
    default Object getSource() {
        return null;
    }
}

接口内部只有一个 getSource() 方法,其含义为:返回此元数据元素的配置源Object (可以为null )。

其实还是不知道啥意思……

在子类(BeanMetadataAttributeAccessor)中加上断点,debug

这里 source 里面存储了 Class 类文件在磁盘的真实路径。当然姑且可以这么认为,毕竟我这也是刚开始学习源码,当前的结论只是 debug 到的,也有可能在别的实现类中存储的是别的信息。

BeanDefinition

BeanDefinition 方法较多,就不贴代码,或者截图了。详细可以通过 我的 GitHub 进行阅读,上面添加了相关注释。

不过还是简要介绍一下方法,大概有 Bean 的名字、作用范围、是否首选、以及 Bean 的初始化销毁方法等等。

BeanDefinition 只是一个接口,其实现又分为好几种。

AbstractBeanDefinition

AbstractBeanDefinition

AbstractBeanDefinition 作为 BeanDefinition 的抽象实现类,内部定义了很多属性,以满足 BeanDefinition 定义的接口功能。

这些属性的操作,就对应着 BeanDefinition 定义的接口方法。

AbstractBeanDefinition 三个实现类

AbstractBeanDefinition 的实现又分为三个:分别是 ChildBeanDefinitionRootBeanDefinitionGenericBeanDefinition

  • ChildBeanDefinition:可以从 Parent Definition 里面继承一些公共定义(初始化方法、销毁方法、是否懒加载等等)不过
  • RootBeanDefinition:定义 Bean Definition 的公共属性,该定义在运行时支持Spring BeanFactory中的特定bean。而 RootBeanDefinition 是不可以设置 parentName 指定 Parent Definition 的。
  • GenericBeanDefinition:是一个通用的 Bean Definition,是一站式服务,用于标准bean定义。像任何bean定义一样,它允许指定一个类以及可选的构造函数参数值和属性值。另外,可以通过 parentName 属性灵活地配置从父bean定义派生的内容。所以现在一般使用 GenericBeanDefinition。

"从 Spring 2.5 开始,以编程方式注册 Bean Definition 的首选方法是 GenericBeanDefinition 类,该类允许通过 GenericBeanDefinition.setParentName 方法动态定义父依赖项。

GenericBeanDefinition 下面还有两个实现:ScannedGenericBeanDefinitionAnnotatedGenericBeanDefinition

二者并无太大区别,只不过 AnnotatedGenericBeanDefinitionScannedGenericBeanDefinition 多了一个 factoryMethodMetadata 的定义。

3

总结

通过阅读 BeanDefinition 的源码,并对其实现类的源码进行阅读之后,大致了解 BeanDefinition 的概念及其含义。大概作图总结如下:

- <End /> -


历史文章 | 相关推荐

  • Spring 源码学习 04:初始化容器与 DefaultListableBeanFactory
  • Spring 源码学习 03:创建 IoC 容器的几种方式
  • Spring 源码学习 02:关于 Spring IoC 和 Bean 的概念

0 人点赞