zoukankan      html  css  js  c++  java
  • 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、参考

  • 相关阅读:
    2 数据库开发--MySQL下载(windows)
    Spring课程 Spring入门篇 3-1 Spring bean装配(上)之bean的配置项及作用域
    Spring课程 Spring入门篇 2-2 Spring注入方式
    Spring课程 Spring入门篇 2-1 IOC和bean容器
    maven课程 项目管理利器-maven 5-1 课程总结 1星(2018-11-08 07:19)
    maven课程 项目管理利器-maven 4-1 使用maven创建web项目 5星
    maven课程 项目管理利器-maven 3-10 maven聚合和继承 4星
    maven课程 项目管理利器-maven 3-9 maven依赖冲突 4星
    maven课程 项目管理利器-maven 3-8 maven依赖传递 4星
    maven课程 项目管理利器-maven 3-7 maven依赖范围 2星
  • 原文地址:https://www.cnblogs.com/wpbxin/p/13550949.html
Copyright © 2011-2022 走看看