美文网首页进制人生程序员
Spring源码系列:BeanDefinition源码解析

Spring源码系列:BeanDefinition源码解析

作者: glmapper_2018 | 来源:发表于2018-02-09 17:59 被阅读110次

    Bean的定义主要由BeanDefinition来描述的。作为Spring中用于包装Bean的数据结构,今天就来看看它的面纱下的真容吧。

    首先就是BeanDefinition的类定义:

    public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement
    

    对,没错,这货是个接口,而不是类,是不是有点莫名奇妙呢?我们都知道在JAVA中,接口是不能用来new出新的对象的,那么在Spring中,到底将XML解析出来的Bean包装成了什么呢?(这个密等下揭开)

    先来看看BeanDefinition一个继承结构吧(均是与BeanDefinition有直接关联的类或者接口)!

    image.png

    从类图中可以看出,BeanDefinition继承了AttributeAccessor和BeanMetadataElement两个接口;一个一个看。

    AttributeAccessor

    AttributeAccessor接口定义了最基本的对任意对象的元数据的修改或者获取,主要方法有:

    //将name定义的属性设置为提供的value值。如果value的值为null,则该属性为{@link #removeAttribute removed}。
    //通常,用户应该注意通过使用完全限定的名称(可能使用类或包名称作为前缀)来防止与其他元数据属性重叠。
    void setAttribute(String name, Object value);
    //获取标识为name的属性的值。
    Object getAttribute(String name);
    //删除标识为name的属性,并返回属性值
    Object removeAttribute(String name);
    //如果名为name的属性是否存在,存在返回true,否则返回false。
    boolean hasAttribute(String name);
    //返回所有属性的名称。
    String[] attributeNames();
    

    BeanMetadataElement

    BeanMetadataElement接口提供了一个getResource()方法,用来传输一个可配置的源对象。

    //返回此元数据元素的配置源对象(可能为null)。
    Object getSource();
    

    BeanDifinition源码分析

    一个BeanDefinition描述了一个bean的实例,包括属性值,构造方法参数值和继承自它的类的更多信息。BeanDefinition仅仅是一个最简单的接口,主要功能是允许BeanFactoryPostProcessor 例如PropertyPlaceHolderConfigure 能够检索并修改属性值和别的bean的元数据(译注)。

    //标准单例作用域的作用域标识符:“singleton”。
    //对于扩展的bean工厂可能支持更多的作用域。
    String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
    
    //标准原型作用域的范围标识符:“prototype”。
    //对于扩展的bean工厂可能支持更多的作用域。
    String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
    
    //表示BeanDefinition是应用程序主要部分的角色提示。 通常对应于用户定义的bean。
    int ROLE_APPLICATION = 0;
    

    ROLE_SUPPORT =1实际上就是说,我这个Bean是用户的,是从配置文件中过来的。

    //表示BeanDefinition是某些大型配置的支持部分的角色提示,通常是一个外部ComponentDefinition。
    //当查看某个特定的ComponentDefinition时,认为bean非常重要,
    //以便在查看应用程序的整体配置时能够意识到这一点。
    int ROLE_SUPPORT = 1;
    

    ROLE_INFRASTRUCTURE = 2就是我这Bean是Spring自己的,和你用户没有一毛钱关系。

    //角色提示表明一个BeanDefinition是提供一个完全背景的角色,并且与最终用户没有关系。
    //这个提示用于注册完全是ComponentDefinition内部工作的一部分的bean
    int ROLE_INFRASTRUCTURE = 2;
    

    上面是BeanDifinition的一些基本属性信息,一个就是标识下当前Bean的作用域,另外就是标识一下这个Bean是内部的还是外部的。下面来看这个接口为其子类都提供了哪些具体的行为方法:

    1.当前Bean父类名称get&set方法

    //如果父类存在,设置这个bean定义的父定义的名称。
    void setParentName(String parentName);
    //如果父类存在,则返回当前Bean的父类的名称
    String getParentName();
    

    2.当前Bean的className get&set方法

    //指定此bean定义的bean类名称。
    //类名称可以在bean factory后期处理中修改,通常用它的解析变体替换原来的类名称。
    void setBeanClassName(String beanClassName);
    
    //返回此bean定义的当前bean类名称。
    //需要注意的是,这不一定是在运行时使用的实际类名,以防子类定义覆盖/继承其父类的类名。
    //此外,这可能只是调用工厂方法的类,或者它 在调用方法的工厂bean引用的情况下甚至可能是空的。
    //因此,不要认为这是在运行时定义的bean类型,而只是将其用于在单独的bean定义级别进行解析。
    String getBeanClassName();
    

    3.Bean的作用域get&set方法

    //覆盖此bean的目标范围,指定一个新的范围名称。
    void setScope(String scope);
    //返回此bean的当前目标作用域的名称,如果没有确定,返回null
    String getScope();
    

    4.懒加载的get&set方法

    //设置这个bean是否应该被延迟初始化。如果{false},那么这个bean将在启动时由bean工厂实例化,
    //这些工厂执行单例的立即初始化。
    //懒加载 <bean lazy-init="true/false">
    void setLazyInit(boolean lazyInit);
    //返回这个bean是否应该被延迟初始化,即不是在启动时立即实例化。只适用于单例bean。
    boolean isLazyInit();
    

    5.依赖关系设置

    //设置这个bean依赖被初始化的bean的名字。 bean工厂将保证这些bean首先被初始化。
    //<bean depends-on="">
    void setDependsOn(String... dependsOn);
    //返回这个bean依赖的bean名称。
    String[] getDependsOn();
    

    6.是否是自动转配设置

    //设置这个bean是否是获得自动装配到其他bean的候选人。
    //需要注意是,此标志旨在仅影响基于类型的自动装配。
    //它不会影响按名称的显式引用,即使指定的bean没有标记为autowire候选,也可以解决这个问题。
    //因此,如果名称匹配,通过名称的自动装配将注入一个bean。
    void setAutowireCandidate(boolean autowireCandidate);
    
    //返回这个bean是否是自动装配到其他bean的候选者。就是是否在其他类中使用autowired来注入当前Bean的
    //是否为被自动装配 <bean autowire-candidate="true/false">
    boolean isAutowireCandidate();
    

    7.主候选Bean

    //是否为主候选bean    使用注解:@Primary
    void setPrimary(boolean primary);
    //返回这个bean是否是主要的autowire候选者。
    boolean isPrimary();
    

    8.定义创建该Bean对象的工厂类

    //指定要使用的工厂bean(如果有的话)。 这是调用指定的工厂方法的bean的名称。
    void setFactoryBeanName(String factoryBeanName);
    //返回工厂bean的名字,如果有的话。
    String getFactoryBeanName();
    

    9.创建该Bean对象的工厂方法

    //如果有的话,指定工厂方法。
    //这个方法先将通过构造函数参数被调用,或者如果参数,将调用该方法的无参数构造。
    //方法将在指定的工厂bean(如果有的话)上被调用,或者作为本地bean类的静态方法被调用。
    void setFactoryMethodName(String factoryMethodName);
    //如果存在,返回工厂方法名
    String getFactoryMethodName();
    

    10.返回此bean的构造函数参数值。

    //返回此bean的构造函数参数值。
    ConstructorArgumentValues getConstructorArgumentValues();
    

    11.获取普通属性集合

    //获取普通属性集合
    MutablePropertyValues getPropertyValues();
    

    12.当前Bean的基本特性

    //是否是单例的
    boolean isSingleton();
    //是否是多例的
    boolean isPrototype();
    //是否是抽象类
    boolean isAbstract();
    

    13.当前Bean的应用

    //获取这个bean的应用
    int getRole();
    

    13.可读描述

    //返回对bean定义的可读描述。
    String getDescription();
    
    //返回该bean定义来自的资源的描述
    String getResourceDescription();
    
    //返回原始的BeanDefinition;如果没有,则返回null。允许检索装饰的bean定义(如果有的话)。
    //注意,这个方法返回直接的发起者。 迭代原始链,找到用户定义的原始BeanDefinition。
    BeanDefinition getOriginatingBeanDefinition();
    

    从上面的属性和方法分析可以看出,BeanDefinition对于一个Bean的描述做了较为完整的一套约束。这为后续的子类提供的最基本的职责和属性。

    欢迎关注glmapper工作室公众号

    [图片上传失败...(image-cef973-1518170383092)]

    相关文章

      网友评论

        本文标题:Spring源码系列:BeanDefinition源码解析

        本文链接:https://www.haomeiwen.com/subject/mvkqtftx.html