Spring源码解析之BeanDefinition
通过阅读本文你能获得什么
- 1、什么是BeanDefinition
- 2、怎么用BeanDefinition定制化开发
为什么要学习BeanDefinition
BeanDefinition看名称可以大致明白是用来描述spring中bean的信息。
如果把spring创建bean类比成工厂生产糖果,工厂生产糖果需要有原材料,没有原材料就没办法生产。那BeanDefinition就是spring创建bean的原材料。可以发现BeanDefinition对整个spring工厂 来说是多么重要,基于这个愿意,给大家分享一下最近学习的BeanDefinition相关的知识
BeanDefinition的定义
上边是类比了一个例子,说BeanDefinition工厂的原材料,但是对于还没有看过Spring源码的人来说,可能还不是很明白。那我这里为大家画一张图,来解释一下。
再来看一下源码中对BD的解释
/**
* A BeanDefinition describes a bean instance, which has property values,
* constructor argument values, and further information supplied by
* concrete implementations.
*/
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
}
从上边的注视中我们可以看到A BeanDefinition describes a bean instance, which has property values ,constructor argument values, and further information supplied by concrete implementations.
这句话 翻译过来就是BeanDefinition描述了一个bean实例,该实例具有属性值,构造函数参数值以及具体实现所提供的更多信息。
AttributeAccessor于BeanMetadataElement 这两个接口会在下边进行介绍
BeanDefinition的类型
先来看一张BeanDefinition的继承关系
从上图中我们看到有以下几个主要的BeanDefinition ,每种BD在spring中的作用不同
- RootBeanDefinition
这个最简单的解释就是在spring中源码中涉及到合并BeanDefinition的时候返回的值都是使用RootBeanDefinition来接受。所以我们可以先理解为它表示合并后的BeanDefinition信息。
- ChildBeanDefinition
看名称我们就能知道这个BeanDefinition应该来表示子的关系,那谁来表示父BD呢?我们可以通过setParentName来手动设置一个父。因为ChildBeanDefinition的构造方法都必须填ParentName所以他只能表示子的概念。
通过javaDoc发现这个类从2.5开始就废弃了推荐使用GenericBeanDefinition
- GenericBeanDefinition
GenericBeanDefinition可以理解为一个通用的BD,因为他既可以表示父也可以表示子,并且javadoc中也明确表示推荐使用。但是为什么不能完全替代RootBeanDefinition?还是如上边说的,因为spring源码中写死了
- AnnotatedBeanDefinition
这个相当于一个标示入口,通过注解编程的spring项目,会以这个bean为入口解析配置类
- AnnotatedGenericBeanDefinition
在解析时是注解的类形成的BeanDefinition
- ScannedGenericBeanDefinition
在解析时通过scan扫描出来的类形成的BeanDefinition
- ConfigurationClassBeanDefinition
标注了@Bean方法创建的beanDefinition
后边这四种BeanDefinition可以理解为自身带有属性因为的BeanDefinition,因为源码中有的会判断instance of 哪个类型来做不同的逻辑处理
BeanDefinition的属性的意义
因为属性比较多,所以直接当作注视写在代码中
package org.springframework.beans.factory.config;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.support.ChildBeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.AttributeAccessor;
import org.springframework.lang.Nullable;
/**
* A BeanDefinition describes a bean instance, which has property values,
* constructor argument values, and further information supplied by
* concrete implementations.
*
* <p>This is just a minimal interface: The main intention is to allow a
* {@link BeanFactoryPostProcessor} such as {@link PropertyPlaceholderConfigurer}
* to introspect and modify property values and other bean metadata.
*
* @author Juergen Hoeller
* @author Rob Harrop
* @since 19.03.2004
* @see ConfigurableListableBeanFactory#getBeanDefinition
* @see org.springframework.beans.factory.support.RootBeanDefinition
* @see org.springframework.beans.factory.support.ChildBeanDefinition
*/
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
/**
* beanDefinition 中的常量值 代表 原型 主要是方便我们程序员在外部调用可以直接使用
* Scope identifier for the standard singleton scope: "singleton".
* <p>Note that extended bean factories might support further scopes.
* @see #setScope
*/
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
/**
* beanDefinition 中的常量值 代表 原型 主要是方便我们程序员在外部调用可以直接使用
* Scope identifier for the standard prototype scope: "prototype".
* <p>Note that extended bean factories might support further scopes.
* @see #setScope
*/
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
/**
* 来标示这个BeanDefinition是应用程序的主要部分通常对应于用户定义的bean
* Role hint indicating that a {@code BeanDefinition} is a major part
* of the application. Typically corresponds to a user-defined bean.
*/
int ROLE_APPLICATION = 0;
/**
* 相对于 ROLE_APPLICATION 而言 ROLE_SUPPORT 不是当前应用的主要部分
* 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.
*/
int ROLE_SUPPORT = 1;
/**
* BeanDefinition 来表式完全在内部起作用的bean 不为我们外部程序员使用
* 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}.
*/
int ROLE_INFRASTRUCTURE = 2;
// Modifiable attributes
/**
* 如果需要给当前的设置BD设置父定义 则通过这个方法来设置
* 结合abstract 来看
* 当前beanDefinition会继承父BD中的信息 子BD有则覆盖
* Set the name of the parent definition of this bean definition, if any.
*/
void setParentName(@Nullable String parentName);
/**
* 获取设置的父定义的名称
* Return the name of the parent definition of this bean definition, if any.
*/
@Nullable
String getParentName();
/**
* 设置bean的class name 实例化的使用使用的类型
* Specify the bean class name of this bean definition.
* <p>The class name can be modified during bean factory post-processing,
* typically replacing the original class name with a parsed variant of it.
* @see #setParentName
* @see #setFactoryBeanName
* @see #setFactoryMethodName
*/
void setBeanClassName(@Nullable String beanClassName);
/**
* 当前Bean的类名称,全路径名。该名称可以在自定义的BeanFactoryPostProcessor中进行修改
* mybatis 结合factoryBean 时就修改了这个属性
*
* Return the current bean class name of this bean definition.
* <p>Note that this does not have to be the actual class name used at runtime, in
* case of a child definition overriding/inheriting the class name from its parent.
* Also, this may just be the class that a factory method is called on, or it may
* even be empty in case of a factory bean reference that a method is called on.
* Hence, do <i>not</i> consider this to be the definitive bean type at runtime but
* rather only use it for parsing purposes at the individual bean definition level.
* @see #getParentName()
* @see #getFactoryBeanName()
* @see #getFactoryMethodName()
*/
@Nullable
String getBeanClassName();