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、参考

 

posted @ 2020-08-23 23:19  心明谭  阅读(498)  评论(0编辑  收藏  举报