Spring5源码分析(013)——IoC篇之解析bean标签:BeanDefinition 和 AbstractBeanDefinition
注:《Spring5源码分析》汇总可参考:Spring5源码分析(002)——博客汇总
前面已经提到, bean 标签配置的相关属性都是 BeanDefinition 来承载,其内部对此提供意义对应的相关属性,本篇单独对 BeanDefinition 进行简要说明,以便对此有一个整体的认知。目录结构如下:
1、BeanDefinition
org.springframework.beans.factory.config.BeanDefinition 描述了一个 bean 实例,包括属性值、构造函数参数值等,由具体实现提供更进一步的信息。
这只是一个最小的接口:主要目的是允许 BeanFactoryPostProcessor 访问内部属性(introspector)并且修改属性值和其他 bean 元数据。
BeanDefinition 内部定义如下:
/** * A BeanDefinition describes a bean instance, which has property values, * constructor argument values, and further information supplied by * concrete implementations. * <p>BeanDefinition 描述了一个 bean 实例,包括属性值、构造函数参数值,由具体实现提供更进一步的信息。 * <p>This is just a minimal interface: The main intention is to allow a * {@link BeanFactoryPostProcessor} to introspect and modify property values * and other bean metadata. * <p>这只是一个最小的接口:主要目的是允许 BeanFactoryPostProcessor 访问 * 内部属性(introspector)并且修改属性值和其他 bean 元数据。 */ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement { /** * Scope identifier for the standard singleton scope: {@value}. * <p>Note that extended bean factories might support further scopes. * @see #setScope * @see ConfigurableBeanFactory#SCOPE_SINGLETON */ String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON; /** * Scope identifier for the standard prototype scope: {@value}. * <p>Note that extended bean factories might support further scopes. * @see #setScope * @see ConfigurableBeanFactory#SCOPE_PROTOTYPE */ String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE; int ROLE_APPLICATION = 0; int ROLE_SUPPORT = 1; int ROLE_INFRASTRUCTURE = 2; // Modifiable attributes void setParentName(@Nullable String parentName); @Nullable String getParentName(); void setBeanClassName(@Nullable String beanClassName); @Nullable String getBeanClassName(); void setScope(@Nullable String scope); @Nullable String getScope(); void setLazyInit(boolean lazyInit); boolean isLazyInit(); void setDependsOn(@Nullable String... dependsOn); @Nullable String[] getDependsOn(); void setAutowireCandidate(boolean autowireCandidate); boolean isAutowireCandidate(); void setPrimary(boolean primary); boolean isPrimary(); void setFactoryBeanName(@Nullable String factoryBeanName); @Nullable String getFactoryBeanName(); void setFactoryMethodName(@Nullable String factoryMethodName); @Nullable String getFactoryMethodName(); ConstructorArgumentValues getConstructorArgumentValues(); default boolean hasConstructorArgumentValues() { return !getConstructorArgumentValues().isEmpty(); } MutablePropertyValues getPropertyValues(); default boolean hasPropertyValues() { return !getPropertyValues().isEmpty(); } void setInitMethodName(@Nullable String initMethodName); @Nullable String getInitMethodName(); void setDestroyMethodName(@Nullable String destroyMethodName); @Nullable String getDestroyMethodName(); void setRole(int role); int getRole(); void setDescription(@Nullable String description); @Nullable String getDescription(); // Read-only attributes ResolvableType getResolvableType(); boolean isSingleton(); boolean isPrototype(); boolean isAbstract(); @Nullable String getResourceDescription(); @Nullable BeanDefinition getOriginatingBeanDefinition(); }
可以看出,这些定义与 bean 标签的属性和子元素基本一一对应。
2、BeanDefinition 体系
在 BeanDefinition 体系 中已经提到 BeanDefinition 的继承结构,这里抄过来:
2.1、BeanDefinition 的父接口
从继承结构中可以看到, BeanDefinition 继承了 2 个父接口,分别是 AttributeAccessor 和 BeanMetadataElement :
- org.springframework.core.AttributeAccessor : 定义了向任意对象附加和访问元数据的通用约定接口,例如对属性的获取、设置、删除等。
/** * Interface defining a generic contract for attaching and accessing metadata * to/from arbitrary objects. * <p>定义了向任意对象附加和访问元数据的通用约定接口,例如对属性的获取、设置、删除等 */ 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(); }
- org.springframework.beans.BeanMetadataElement : 用于获取 bean 配置元数据元素的配置源
/** * Interface to be implemented by bean metadata elements * that carry a configuration source object. * <p>用于获取 bean 配置元数据元素的配置源 */ public interface BeanMetadataElement { /** * Return the configuration source {@code Object} for this metadata element * (may be {@code null}). */ @Nullable default Object getSource() { return null; } }
2.2、BeanDefinition 的子类
BeanDefinition 的抽象子类 AbstractBeanDefinition 进行了一些基本方法的通用实现,这里我们主要关系3个实现类:
- org.springframework.beans.factory.support.GenericBeanDefinition
- org.springframework.beans.factory.support.RootBeanDefinition
- org.springframework.beans.factory.support.ChildBeanDefinition
这3个实现类都继承了 AbstractBeanDefinition 。在配置文件中可以定义父 <bean> 和子 <bean> ,其中,父 <bean> 用 RootBeanDefinition 表示,子 <bean> 用 ChildBeanDefinition 表示,而没有父 <bean> 的则使用 RootBeanDefinition 进行表示,可以说 RootBeanDefinition 是最常用的实现类,对应一般性的<bean>元素标签。而 GenericBeanDefinition 则是自 2.5 版本以后新加入的 bean 文件配置属性定义类,是一站式服务类:
/** * GenericBeanDefinition is a one-stop shop for standard bean definition purposes. * Like any bean definition, it allows for specifying a class plus optionally * constructor argument values and property values. Additionally, deriving from a * parent bean definition can be flexibly configured through the "parentName" property. * <p>用于标准 bean 定义的一站式服务类。与其他任意 bean 定义一样,它允许指定类以及可选 * 的构造器参数和属性值。此外,可以通过 parentName 属性灵活的配置父 bean 定义 * * <p>In general, use this {@code GenericBeanDefinition} class for the purpose of * registering user-visible bean definitions (which a post-processor might operate on, * potentially even reconfiguring the parent name). Use {@code RootBeanDefinition} / * {@code ChildBeanDefinition} where parent/child relationships happen to be pre-determined. * <p>通常,使用这个 GenericBeanDefinition 类来注册用户可见的bean定义(后处理器可能对其进行操作, * 甚至可能重新配置 parentName )。如果父/子关系是预先确定的,请使用 RootBeanDefinition / ChildBeanDefinition。 * * @author Juergen Hoeller * @since 2.5 * @see #setParentName * @see RootBeanDefinition * @see ChildBeanDefinition */ @SuppressWarnings("serial") public class GenericBeanDefinition extends AbstractBeanDefinition { @Nullable private String parentName; // .... }
2.3、抽象子类 AbstractBeanDefinition 的属性
解析过程中使用的是 AbstractBeanDefinition ,这里我们重点看下对应的属性:
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor implements BeanDefinition, Cloneable { /// 忽略一堆 static final 属性 @Nullable private volatile Object beanClass; /** * bean 的作用范围,对应 bean 属性 scope */ @Nullable private String scope = SCOPE_DEFAULT; /** * 是否抽象,对应 bean 属性 abstract */ private boolean abstractFlag = false; /** * 是否延迟加载,对应 bean 属性 lazy-init */ @Nullable private Boolean lazyInit; /** * 自动诸如模式,对应 bean 属性 autowire */ private int autowireMode = AUTOWIRE_NO; /** * 依赖检查,Spring3.0之后弃用这个属性 */ private int dependencyCheck = DEPENDENCY_CHECK_NONE; /** * 用来表示一个 bean 的实例化依靠另一个 bean 先实例化,对应 bean 属性 depend-on */ @Nullable private String[] dependsOn; /** * autowire-candidate 属性这只为 true ,这样容器在查找自动装配对象时,将不考虑该 bean , * 即它不会倍考虑作为其他 bean 自动装配的候选者,但是该 bean 本身是可以使用自动装配来 * 注入其他 bean 的 */ private boolean autowireCandidate = true; /** * 自动装配时当出现多个 bean 候选者时,将作为首选者,对应 bean 属性 primary */ private boolean primary = false; /** * 用于记录 Qualifier ,对应子元素 qualifier */ private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>(); @Nullable private Supplier<?> instanceSupplier; /** * 允许访问非公开的构造器和方法 */ private boolean nonPublicAccessAllowed = true; /** * 是否以一种宽松的模式解析构造函数,默认 true */ private boolean lenientConstructorResolution = true; /** * 对应 bean 属性 factory-bean */ @Nullable private String factoryBeanName; /** * 对应 bean 属性 factory-method */ @Nullable private String factoryMethodName; /** * 记录构造函数注入属性,对应 bean 属性 constructor-arg */ @Nullable private ConstructorArgumentValues constructorArgumentValues; /** * 普通属性 property 集合 */ @Nullable private MutablePropertyValues propertyValues; /** * 方法重写的持有者,记录 lookup-method 和 replaced-method 元素 */ private MethodOverrides methodOverrides = new MethodOverrides(); /** * 初始化方法,对应 bean 属性 init-method */ @Nullable private String initMethodName; /** * 销毁方法,对应 bean 属性 destroy-method */ @Nullable private String destroyMethodName; /** * 是否执行 init-method 方法 */ private boolean enforceInitMethod = true; /** * 是否执行 destroy-method 方法 */ private boolean enforceDestroyMethod = true; /** * 是否是用户定义的而不是应用程序本身定义的,创建 AOP 时为 true ,程序设置 */ private boolean synthetic = false; /** * 定义这个 bean 的角色范围,ROLE_APPLICATION:用户;ROLE_INFRASTRUCTURE:完全内部使用,与用户无关; * ROLE_SUPPORT:某些复杂配置的一部分程序设置 */ private int role = BeanDefinition.ROLE_APPLICATION; /** * bean 的描述信息 */ @Nullable private String description; /** * bean 定义涉及到的资源 */ @Nullable private Resource resource; ///.... }
可以看到一些比较常用的属性定义了,后面相关元素或者属性的解析都会一一对应上。
3、总结
至此,我们可以看出: BeanDefinition 其实就是 spring 内部对 bean 标签的表示形式。后续将一一进行 bean 标签具体属性和子元素的解析分析。
4、参考
- spring 官方文档 5.2.3.RELEASE:https://docs.spring.io/spring-framework/docs/5.2.3.RELEASE/spring-framework-reference/core.html
- Spring源码深度解析(第2版),郝佳,P44-P72
- 相关注释可参考笔者 github 链接:https://github.com/wpbxin/spring-framework