美文网首页
2-BeanDefinition

2-BeanDefinition

作者: 鹏程1995 | 来源:发表于2020-02-14 17:37 被阅读0次

背景简介

本文主要对 BeanDefinition接口进行简单的介绍。

出现的原因

在 Spring 工作时,明显的分成两个阶段:

  1. 从配置中读取信息,并生成此项目对应的 Bean 的定义,缓存在内存中。
  2. 用户【可能是人也可能是应用程序、应用框架】根据需要指示 Spring 生成指定的 bean 实例。

所以需要一个至关重要的数据结构,来缓存从配置中读取的 Bean 的定义。

职责

缓存创建 Bean 所需的一切信息。

BeanDefinition主要指责如下:

  1. 对 Bean 的创建的所有可能用到的字段进行了存取方法的定义
  2. 对 Bean 的创建中可能用到的一些常量进行了定义

注意:既然是对从配置中读取的信息的处理结果,考虑到很多依赖于 Spring 的框架的扩展问题。 BeanDefinition还对生成自己的配置做了一个保存,方便用户进行自行定制。【此处有一些想法,参见"想法——程序员的思维"

源码

继承关系

根据上面的职责大概能猜到,BeanDefinition中就是一些getter/setter方法、一些常量定义。其中的getter/setter方法中包括了创建 Bean 实例所有可能用到的字段。所以它继承了两个接口:

  1. AttributeAccessor:定义了通用的getter/setter,有点像 Map操作规范那种
  2. BeanMetadataElement: 定义了一个方法,用来获得生成此BeanDefinition的数据源
1.png

定义的常量

/**
 * 单例 Bean 的生命周期常量
 *
 * 注意,具体的实现类可能会扩展其他的生命周期常量。
 *
 * @see #setScope
 */
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;

/**
 * 原型 Bean 的生命周期常量
 *
 * 注意,具体的实现类可能会扩展其他的生命周期常量。
 *
 * @see #setScope
 */
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;


/**
 * Role hint indicating that a {@code BeanDefinition} is a major part
 * of the application. Typically corresponds to a user-defined bean.
 */
// 角色提示。表明这个 BD 是应用中的关键角色。这个角色通常对应用户定义的 Bean
int ROLE_APPLICATION = 0;

/**
 * Role hint indicating that a {@code BeanDefinition} is a supporting
 * part of some larger configuration, typically an outer
 * {@link org.springframework.beans.factory.parsing.ComponentDefinition}.
 * {@code SUPPORT} beans are considered important enough to be aware
 * of when looking more closely at a particular
 * {@link org.springframework.beans.factory.parsing.ComponentDefinition},
 * but not when looking at the overall configuration of an application.
 */
// 角色提示,表明 BD 是一些大型配置的支撑角色。通常是一些外部框架的支撑 bean 。在梳理整体应用
// 配置时一般不关心它,但是在仔细查看特定框架实现时应该注意研读
int ROLE_SUPPORT = 1;

/**
 * Role hint indicating that a {@code BeanDefinition} is providing an
 * entirely background role and has no relevance to the end-user. This hint is
 * used when registering beans that are completely part of the internal workings
 * of a {@link org.springframework.beans.factory.parsing.ComponentDefinition}.
 */
// 角色提示,表示 BD 完全是一个后台服务,不会和使用者直接接触。在注册完全在 ComponentDefinition 内部工作
// 的 BD 时会用这个
int ROLE_INFRASTRUCTURE = 2;

主要围绕 Bean 的生命周期和角色定义了一些常见的常量。

问题

为什么没有用 final修饰,会不会被篡改?见最后的扩展。

定义的变量getter/setter

因为直接粘贴源码太长了,我们直接去掉get/set取后面的名字来大概介绍都定义了哪些属性。

  • ParentName: 返回此 BeanDefinition的父BD的名称【id 或者 别名】
  • BeanClassName: Bean 实例对应的类名【为什么不直接返回 Class类型呢?参见"想法——职责单一问题”】
  • Scope:类的生命周期
  • LazyInit:Bean 的初始化是否进行懒加载
  • DependsOn:设置此 Bean 明确配置的依赖的 Bean。【后面会了解到,如果你在 Bean 中使用了对其他 Bean 的依赖注入,这个也算依赖,后面会维护在 Factory中。但是允许你主动配置或者新增对一些 Bean 的依赖】
  • AutowireCandidate: 判断其他 Bean 是否允许依赖注入此 Bean
  • Primary: 其他 Bean 做依赖注入有多个候选人时,是否优先选此 Bean
  • FactoryBeanName:在使用工厂方法构造此 BD 的实例时,使用哪个工厂
  • FactoryMethodName:在使用工厂方法构造此 BD 的实例时,使用工厂的哪个方法
  • ConstructorArgumentValues: 使用构造函数创建此 BD 的实例时,配置了哪些入参
  • PropertyValues:创建实例后使用getter/setter方法填充实例属性时,要配置哪些入参
  • Role: BD 对应的实例的角色
  • ResourceDescription: 获得创建这个 BD 的源的描述信息
  • Source: 获得创建这个 BD 的源
  • OriginatingBeanDefinition:未知。。。。。。。。。

还有基于以上属性的一些判断函数,例如是不是单例、是不是原型之类的,不再赘述。

一些想法

程序员的思维

关于在写代码,搭建框架甚至是日常工作中的一些操作的思路:

  1. 尽可能的使用封装之后的东西,这样有问题你能找到负责的人,使用顺畅。而且封装之后往往意味着使用更加简单。【API接口】
  2. 在工作时对 API 问题进行沟通时尽可能绕过行话直接说原理,这样调用者能更好的把控整个流程,有时还能帮你找出一些问题。
  3. 在提供 SPI 时,和 API 不同的是,如果可行的话,提供一个接口,让调用者能够拿到最原始的数据,这样会使框架在某些情况下更方便用户进行定制。当然,要对自己的解析流程定好规范和校验,防止由于用户的不规范操作造成大范围的问题。

职责单一问题

在定义数据结构时,要明确你要的是什么?

BD的职责只是一个用于存储的数据结构而已,在存储 Bean 对应的类时采用String足以存储,该类名是从配置文件中读取的。不一定是对的,可能该类不存在,也可能未加载,如果在这里就传入Class,那么在最开始的注册阶段就会引起大量的冗余引入、校验操作。

扩展

interface中的常量定义没有用修饰词

  • interface中的常量定义不用修饰,都是public static final
  • interface中定义的方法不用修饰,都是public

丢人!!!!

相关文章

  • 2-BeanDefinition

    背景简介 本文主要对 BeanDefinition接口进行简单的介绍。 出现的原因 在 Spring 工作时,明显...

网友评论

      本文标题:2-BeanDefinition

      本文链接:https://www.haomeiwen.com/subject/mcdjfhtx.html