ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Spring源码1-BeanDefinition 解析

2022-05-28 11:00:30  阅读:158  来源: 互联网

标签:String boolean Spring private int Bean 源码 BeanDefinition


前言

Spring容器 中一个非常重要的概念: BeanDefinition

注:本文springboot、spring版本如下图

Spring容器的强大之处:获取对象时,不需要我们手工主动new对象,完全交给Spring容器管理。

Spring 将管理的对象称之为 Bean,容器会先实例化 Bean,然后自动注入,实例化的过程就需要依赖 BeanDefinition。

BeanDefinition 用于保存 Bean 的相关信息,包括属性、构造方法参数、依赖的 Bean 名称及是否单例、延迟加载等,它是实例化 Bean 的原材料,Spring 就是根据 BeanDefinition 中的信息实例化 Bean。

 

BeanDefinition对象详解

BeanDefinition是一个接口类,实现类以及子接口很多,如下:

BeanDefinition 用于保存 Bean 的相关信息,包括属性、构造方法参数、依赖的 Bean 名称及是否单例、延迟加载等,详细核心内容如下:

/**

BeanDefinition描述了一个bean实例,它有属性值,
构造函数参数值,以及提供的进一步信息
具体实现。
这只是一个最小的接口:主要目的是允许一个
{@link BeanFactoryPostProcessor}来自省和修改属性值
和其他bean元数据。

 * @see ConfigurableListableBeanFactory#getBeanDefinition
 * @see org.springframework.beans.factory.support.RootBeanDefinition
 * @see org.springframework.beans.factory.support.ChildBeanDefinition
 */
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    /**
     * 标准单例、原型模式标识符
     * @see #setScope
     * @see ConfigurableBeanFactory#SCOPE_SINGLETON
     */
    String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
    String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

    /**
     * 标识Bean的类别 0-用户定义的Bean  1-来源于配置文件的Bean 2-Spring内部的Bean*/
    int ROLE_APPLICATION = 0;
    int ROLE_SUPPORT = 1;
    int ROLE_INFRASTRUCTURE = 2;

    // Modifiable attributes
    /**
     * 设置、返回父类名称
     */
    void setParentName(@Nullable String parentName);
    String getParentName();

    /**
     * 设置、返回 className
     * @see #setParentName
     * @see #setFactoryBeanName
     * @see #setFactoryMethodName
     */
    void setBeanClassName(@Nullable String beanClassName);
    String getBeanClassName();

    /**
     * 设置、返回作用域
     * @see #SCOPE_SINGLETON
     * @see #SCOPE_PROTOTYPE
     */
    void setScope(@Nullable String scope);
    String getScope();

    /**
     * 设置、返回 是否懒加载*/
    void setLazyInit(boolean lazyInit);
    boolean isLazyInit();

    /**
     * 设置、返回当前Bean对象所依赖的其他Bean名称
     */
    void setDependsOn(@Nullable String... dependsOn);
    String[] getDependsOn();

    /**
     *设置、返回是否可以自动注入,对应@Autowired 注解
     */
    void setAutowireCandidate(boolean autowireCandidate);
    boolean isAutowireCandidate();

    /**
     * 设置、返回当前Bean 是否为主要候选Bean  一个接口多个实例对象,可以通过此属性来设置指定具体实例对象*/
    void setPrimary(boolean primary);
    boolean isPrimary();

    /**
     * 设置、返回Bean的工长类*/
    void setFactoryBeanName(@Nullable String factoryBeanName);
    String getFactoryBeanName();

    /**
     * 工厂方法
     * @see #setFactoryBeanName
     * @see #setBeanClassName
     */
    void setFactoryMethodName(@Nullable String factoryMethodName);
    String getFactoryMethodName();

    /**
     *返回构造参数值、属性值*/
    ConstructorArgumentValues getConstructorArgumentValues();
    default boolean hasConstructorArgumentValues() {
        return !getConstructorArgumentValues().isEmpty();
    }
    MutablePropertyValues getPropertyValues();
    default boolean hasPropertyValues() {
        return !getPropertyValues().isEmpty();
    }

    /**
     * 初始化方法名称*/
    void setInitMethodName(@Nullable String initMethodName);
    String getInitMethodName();

    /**
     * 销毁方法的名称*/
    void setDestroyMethodName(@Nullable String destroyMethodName);
    String getDestroyMethodName();

    /**
     * Bean的类别
     * @see #ROLE_APPLICATION
     * @see #ROLE_SUPPORT
     * @see #ROLE_INFRASTRUCTURE
     */
    void setRole(int role);
    int getRole();
    ........ 此处省略其他源码

}

AnnotatedBeanDefinition

AnnotatedBeanDefinition 是 BeanDefinition 子接口之一,该接口扩展了 BeanDefinition 的功能,其用来操作注解元数据。一般情况下,通过注解方式得到的 Bean(@Component、@Bean)。

public interface AnnotatedBeanDefinition extends BeanDefinition {

    // 获得当前 Bean 的注解元数据
    AnnotationMetadata getMetadata();

    // 获得当前 Bean 的工厂方法上的元数据
    MethodMetadata getFactoryMethodMetadata();
}

该接口可以返回两个元数据的类:

  • AnnotationMetadata:主要对 Bean 的注解信息进行操作,如:获取当前 Bean 标注的所有注解、判断是否包含指定注解。

  • MethodMetadata:方法的元数据类。提供获取方法名称、此方法所属类的全类名、是否是抽象方法、判断是否是静态方法、判断是否是final方法等。

AbstractBeanDefinition

AbstractBeanDefinition 是 BeanDefinition 的子抽象类,也是其他 BeanDefinition 类型的基类,其实现了接口中定义的一系列操作方法,并定义了一系列的常量属性,这些常量会直接影响到 Spring 实例化 Bean 时的策略。核心属性如下。

public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
        implements BeanDefinition, Cloneable {

    // 默认的 SCOPE,默认是单例
    public static final String SCOPE_DEFAULT = "";

    // 不进行自动装配
    public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;
    // 根据 Bean 的名字进行自动装配,byName
    public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
    // 根据 Bean 的类型进行自动装配,byType
    public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
    // 根据构造器进行自动装配
    public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
    // 首先尝试按构造器自动装配。如果失败,再尝试使用 byType 进行自动装配。(Spring 3.0 之后已废除)
    public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;

    // 通过依赖检查来查看 Bean 的每个属性是否都设置完成
    // 以下常量分别对应:不检查、对依赖对象检查、对基本类型,字符串和集合进行检查、对全部属性进行检查
    public static final int DEPENDENCY_CHECK_NONE = 0;
    public static final int DEPENDENCY_CHECK_OBJECTS = 1;
    public static final int DEPENDENCY_CHECK_SIMPLE = 2;
    public static final int DEPENDENCY_CHECK_ALL = 3;

    // 关闭应用上下文时需调用的方法名称
    public static final String INFER_METHOD = "(inferred)";

    // 存放 Bean 的 Class 对象
    private volatile Object beanClass;

    // Bean 的作用范围
    private String scope = SCOPE_DEFAULT;

    // 非抽象
    private boolean abstractFlag = false;
    // 非延迟加载
    private boolean lazyInit = false;
    // 默认不自动装配
    private int autowireMode = AUTOWIRE_NO;
    // 默认不依赖检查
    private int dependencyCheck = DEPENDENCY_CHECK_NONE;

    // 依赖的 Bean 列表
    private String[] dependsOn;

    // 可以作为自动装配的候选者,意味着可以自动装配到其他 Bean 的某个属性中
    private boolean autowireCandidate = true;
    
    // 创建当前 Bean 实例工厂类名称
    private String factoryBeanName;
    // 创建当前 Bean 实例工厂类中方法名称
    private String factoryMethodName;

    // 存储构造方法的参数
    private ConstructorArgumentValues constructorArgumentValues;
    // 存储 Bean 属性名称以及对应的值
    private MutablePropertyValues propertyValues;
    // 存储被覆盖的方法信息
    private MethodOverrides methodOverrides;

    // init、destroy 方法名称
    private String initMethodName;
    private String destroyMethodName;

    // 是否执行 init 和 destroy 方法
    private boolean enforceInitMethod = true;
    private boolean enforceDestroyMethod = true;

    // Bean 是否是用户定义的而不是应用程序本身定义的
    private boolean synthetic = false;

    // Bean 的身份类别,默认是用户定义的 Bean
    private int role = BeanDefinition.ROLE_APPLICATION;

    // Bean 的描述信息
    private String description;

    // Bean 定义的资源
    private Resource resource;
    
    .......
}

 

以上是 AbstractBeanDefinition 中定义的一些常量和属性,该类中还有一部分是操作这些属性的 set 和 get 方法,这些方法都由子类来操作,且应用程序中真正使用的也是这些子类 BeanDefinition。

先来看 AbstractBeanDefinition 直接实现类:RootBeanDefinition、GenericBeanDefinition、ChildBeanDefinition。

RootBeanDefinition

该类继承自 AbstractBeanDefinition,它可以单独作为一个 BeanDefinition,也可以作为其他 BeanDefinition 的父类。

RootBeanDefinition 在 AbstractBeanDefinition 的基础上定义了更多属性。

public class RootBeanDefinition extends AbstractBeanDefinition {

    // BeanDefinitionHolder 存储 Bean 的名称、别名、BeanDefinition
    private BeanDefinitionHolder decoratedDefinition;

    // AnnotatedElement 是java反射包的接口,通过它可以查看 Bean 的注解信息
    private AnnotatedElement qualifiedElement;

    // 允许缓存
    boolean allowCaching = true;
    
    // 工厂方法是否唯一
    boolean isFactoryMethodUnique = false;

    // 封装了 java.lang.reflect.Type,提供了泛型相关的操作
    volatile ResolvableType targetType;

    // 缓存 Class,表示 RootBeanDefinition 存储哪个类的信息
    volatile Class<?> resolvedTargetType;

    // 缓存工厂方法的返回类型
    volatile ResolvableType factoryMethodReturnType;

    // 这是以下四个构造方法字段的通用锁
    final Object constructorArgumentLock = new Object();
    // 用于缓存已解析的构造方法或工厂方法
    Executable resolvedConstructorOrFactoryMethod;
    // 将构造方法参数标记为已解析
    boolean constructorArgumentsResolved = false;
    // 用于缓存完全解析的构造方法参数
    Object[] resolvedConstructorArguments;
    // 缓存待解析的构造方法参数
    Object[] preparedConstructorArguments;

    // 这是以下两个后处理字段的通用锁
    final Object postProcessingLock = new Object();
    // 表明是否被 MergedBeanDefinitionPostProcessor 处理过
    boolean postProcessed = false;
    // 在生成代理的时候会使用,表明是否已经生成代理
    volatile Boolean beforeInstantiationResolved;

    // 实际缓存的类型是 Constructor、Field、Method 类型
    private Set<Member> externallyManagedConfigMembers;

    // InitializingBean中 的 init 回调函数名 afterPropertiesSet 会在这里记录,以便进行生命周期回调
    private Set<String> externallyManagedInitMethods;

    // DisposableBean 的 destroy 回调函数名 destroy 会在这里记录,以便进生命周期回调
    private Set<String> externallyManagedDestroyMethods;

    ......
}

ChildBeanDefinition

该类继承自 AbstractBeanDefinition。其相当于一个子类,不可以单独存在,必须依赖一个父 BeanDetintion,构造 ChildBeanDefinition 时,通过构造方法传入父 BeanDetintion 的名称或通过 setParentName 设置父名称。它可以从父类继承方法参数、属性值,并可以重写父类的方法,同时也可以增加新的属性或者方法。若重新定义 init 方法,destroy 方法或者静态工厂方法,ChildBeanDefinition 会重写父类的设置。

从 Spring 2.5 开始,以编程方式注册 Bean 定义的首选方法是 GenericBeanDefinition,GenericBeanDefinition 可以有效替代 ChildBeanDefinition 的绝大分部使用场合。

GenericBeanDefinition

GenericBeanDefinition 是 Spring 2.5 以后新引入的 BeanDefinition,是 ChildBeanDefinition 更好的替代者,它同样可以通过 setParentName 方法设置父 BeanDefinition。

最后三个 BeanDefinition 既实现了 AnnotatedBeanDefinition 接口,又间接继承 AbstractBeanDefinition 抽象类,这些 BeanDefinition 描述的都是注解形式的 Bean。

ConfigurationClassBeanDefinition

该类继承自 RootBeanDefinition ,并实现了 AnnotatedBeanDefinition 接口。这个 BeanDefinition 用来描述在标注 @Configuration 注解的类中,通过 @Bean 注解实例化的 Bean。

其功能特点如下:

1、如果 @Bean 注解没有指定 Bean 的名字,默认会用方法的名字命名 Bean。

2、标注 @Configuration 注解的类会成为一个工厂类,而标注 @Bean 注解的方法会成为工厂方法,通过工厂方法实例化 Bean,而不是直接通过构造方法初始化。

3、标注 @Bean 注解的类会使用构造方法自动装配

AnnotatedGenericBeanDefinition

该类继承自 GenericBeanDefinition ,并实现了 AnnotatedBeanDefinition 接口。这个 BeanDefinition 用来描述标注 @Configuration 注解的 Bean。

ScannedGenericBeanDefinition

该类继承自 GenericBeanDefinition ,并实现了 AnnotatedBeanDefinition 接口。这个 BeanDefinition 用来描述标注 @Component 注解的 Bean,其派生注解如 @Service、@Controller 也同理。

总结

BeanDefinition 主要是用来描述 Bean,其存储了 Bean 的相关信息,Spring 实例化 Bean 时需读取该 Bean 对应的 BeanDefinition。BeanDefinition 整体可以分为两类,一类是描述通用的 Bean,还有一类是描述注解形式的 Bean。一般前者在 XML 时期定义 <bean‘> 标签以及在 Spring 内部使用较多,而现今我们大都使用后者,通过注解形式加载 Bean。

 

标签:String,boolean,Spring,private,int,Bean,源码,BeanDefinition
来源: https://www.cnblogs.com/chch213/p/16320061.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有