BeanDefinition的父接口

上回书讲了BeanDefinition的基础知识,本篇文章咱们详细讨论BeanDefinition家族体系。 在讲解之前笔者再一次祭出BeanDefinition家族继承关系图:

 

java

复制代码

/*** BeanDefinition接口的父接口: 1. AttributeAccessor         1.1 实现类 AttributeAccessorSupport 作用是操作bd的属性,属性存放在LinkedHashMap。 2. BeanMetadataElement         2.1 实现类 BeanMetadataAttributeAccessor获取源即bd对应的class的磁盘文件位置 2.2 实现类 BeanMetadataAttributeAccessor继承了AttributeAccessorSupport既可以操作属性值,也可以操作源         2.3 属性封装对象 BeanMetadataAttribute ***/ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement

1.BeanDefinition的父接口

上一篇博文详细讲了接口BeanDefinition的功能,笔者打算围绕该接口进行扩展。

首先看下BeanDefinition的父接口有哪些:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement

BeanDefinition接口继承了AttributeAccessor和BeanMetadataElement两个接口。

也就是说BeanDefinition的实现类同时实现了

BeanDefinition 、AttributeAccessor、BeanMetadataElement三个接口的功能。

1.1 AttributeAccessor:作用操作bd属性

 

java

复制代码

/** *定义用于附加和访问BeanDefinition元数据的通用的接口,来自任意对象 */ public interface AttributeAccessor {    /**   将属性名为name的属性的属性值设置为value   注意是BeanDefinition的属性   */    void setAttribute(String name, Object value);    /**    获取指定name的属性值,如果该属性不存在,则返回Null    注意是BeanDefinition的属性    */    Object getAttribute(String name);    /**   删除指定name的属性值,如果找不到Nmae属性的值则返回Null   注意是BeanDefinition的属性   */    Object removeAttribute(String name);    /**    如果属性名为name的属性存在则返回true,否者返回false    注意是BeanDefinition的属性    */    boolean hasAttribute(String name);    /**    返回所有的属性名称    注意是BeanDefinition的属性     */    String[] attributeNames(); }

该接口定义用于附加和访问BeanDefinition元数据,我们知道,接口只是定义了操作方法,这个接口的方法很简单,但我们看不出这个接口到底代表啥意思呢,回头看继承图,找到这个接口唯一的实现类AttributeAccessorSupport:

1.1.1实现类AttributeAccessorSupport

 

java

复制代码

public abstract class AttributeAccessorSupport implements AttributeAccessor, Serializable {    /** Map with String keys and Object values. */    //用于存放属性键值对    private final Map<String, Object> attributes = new LinkedHashMap<>();    //设置属性值 value是BeanMetadataAttribute类型    @Override    public void setAttribute(String name, @Nullable Object value) {        Assert.notNull(name, "Name must not be null");        if (value != null) {            this.attributes.put(name, value);       }        else {            removeAttribute(name);       }   }    //获取属性值 value是BeanMetadataAttribute类型    @Override    @Nullable    public Object getAttribute(String name) {        Assert.notNull(name, "Name must not be null");        return this.attributes.get(name);   }     //删除属性值    @Override    @Nullable    public Object removeAttribute(String name) {        Assert.notNull(name, "Name must not be null");        return this.attributes.remove(name);   }   //判断是否有属性值    @Override    public boolean hasAttribute(String name) {        Assert.notNull(name, "Name must not be null");        return this.attributes.containsKey(name);   }     //获取所有属性值名字    @Override    public String[] attributeNames() {        return StringUtils.toStringArray(this.attributes.keySet());   }    //内部使用,属性值的拷贝    /**     * Copy the attributes from the supplied AttributeAccessor to this accessor.     * @param source the AttributeAccessor to copy from     */    protected void copyAttributesFrom(AttributeAccessor source) {        Assert.notNull(source, "Source must not be null");        String[] attributeNames = source.attributeNames();        for (String attributeName : attributeNames) {            setAttribute(attributeName, source.getAttribute(attributeName));       }   }    //重写equals方法,判断是否与别的属性类共用一个存储结构,即判断LinkedHashMap是否相等    @Override    public boolean equals(Object other) {        return (this == other || (other instanceof AttributeAccessorSupport &&                this.attributes.equals(((AttributeAccessorSupport) other).attributes)));   }    @Override    public int hashCode() {        return this.attributes.hashCode();   } }

其实,这个实现类我们还是看不出他跟BeanDefinition有什么关系。但是我们搞清楚一点,就是AttributeAccessorSupport就是在维护一个LinkedHashMap而已。BeanDefinition的某些属性值就存储在这个LinkedHashMap中,是哪些属性值呢?看下面代码:

 

java

复制代码

public class SpringTest {    public static void main(String[] args) throws InterruptedException {        AnnotationConfigApplicationContext context = new           AnnotationConfigApplicationContext();        //注册配置类        context.register(Config.class);        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();        beanDefinition.setBeanClassName("com.InterService");        //设置属性值        beanDefinition.setAttribute("AttributeAccessor","源码之路");        //将beanDefinition注册到spring容器中        context.registerBeanDefinition("interService",beanDefinition);        //加载或者刷新当前的配置信息        context.refresh();        //拿到属性信息        String[] attributes = context.getBeanDefinition("interService").attributeNames();   } }

查看interService对应的beanDefinition的attribute。

我们知道BeanDefinition用来描述你的业务类,那么,谁来描述BeanDefitino呢?

就是通过设置属性值来描述的!

比如beanDefinition的代理模式等,以后会讲到。这里的FULL和LITE就是是否生成代理的标志!

具体区别可参考: blog.csdn.net/tales522/ar…

1.2 BeanMetadataElement:作用是获取bd对应的class的磁盘文件位置

 

java

复制代码

public interface BeanMetadataElement {    //获取源对象,可能返回null    Object getSource(); }

BeanDefinition中存了业务类在虚拟机中的class,这个上篇博文讲了。

但是这个class文件存在你电脑硬盘哪里呢?

getSource翻译成中文就是获取源,对象的源是class,那class的源就是你硬盘上的文件。看下面代码:

 

java

复制代码

public class SpringTest {    public static void main(String[] args) throws InterruptedException {        AnnotationConfigApplicationContext context = new       AnnotationConfigApplicationContext();        //注册配置类        context.register(Config.class);        //加载或者刷新当前的配置信息        context.refresh();        //获取InterService.class的源        System.out.println(context.getBeanDefinition("interService").getSource());   } } //输出:file [E:\study\spring-framework\source-code\out\production\classes\tyrant\InterService.class]

1.2.1 实现:BeanMetadataAttributeAccessor

BeanMetadataElement接口提供了获取源的抽象方法。

真正的实现是在它的实现类BeanMetadataAttributeAccessor中。

BeanMetadataAttributeAccessor继承了AttributeAccessorSupport并且实现了BeanMetadataElement接口。

AttributeAccessorSupport实现了上面的AttributeAccessor。

我们看一下它的源码:

 

java

复制代码

public class BeanMetadataAttributeAccessor extends AttributeAccessorSupport implements BeanMetadataElement {    @Nullable    private Object source;    /**     * Set the configuration source {@code Object} for this metadata element.     * <p>The exact type of the object will depend on the configuration mechanism used.     * 设置源     */    public void setSource(@Nullable Object source) {        this.source = source;   }    @Override    @Nullable    //获取源    public Object getSource() {        return this.source;   }    //设置属性值,如果已经存在就覆盖,不存在就添加,BeanMetadataAttribute封装了键值对 //注意value是1个BeanMetadataAttribute    public void addMetadataAttribute(BeanMetadataAttribute attribute) { //super指的是AttributeAccessorSupport //AttributeAccessorSupport中维护了1个LinkedHashMap用于存放BD的属性        super.setAttribute(attribute.getName(), attribute);   }    /**     * 根据名字获取属性键值对的封装对象BeanMetadataAttribute     */    @Nullable    public BeanMetadataAttribute getMetadataAttribute(String name) { //super指的是AttributeAccessorSupport //AttributeAccessorSupport中维护了1个LinkedHashMap用于存放BD的属性        return (BeanMetadataAttribute) super.getAttribute(name);   }    //设置属性值,name表示键,value表示值    @Override    public void setAttribute(String name, @Nullable Object value) {        super.setAttribute(name, new BeanMetadataAttribute(name, value));   }    @Override    @Nullable    //根据键获取属性值    public Object getAttribute(String name) {        BeanMetadataAttribute attribute = (BeanMetadataAttribute)           super.getAttribute(name);        return (attribute != null ? attribute.getValue() : null);   }    @Override    @Nullable    //移除属性值,并返回值,不存在就返回空    public Object removeAttribute(String name) {        BeanMetadataAttribute attribute            = (BeanMetadataAttribute) super.removeAttribute(name);        return (attribute != null ? attribute.getValue() : null);   } }

BeanMetadataAttributeAccessor不但继承了AttributeAccessorSupport还实现了BeanMetadataElement,换言之,既可以操作属性值,也可以操作源。

1.2.1.1BeanMetadataAttribute

上面代码中的BeanMetadataAttribute其实就是对BeanDefinition的属性的键值对进行了封装,如下:

 

java

复制代码

public class BeanMetadataAttribute implements BeanMetadataElement {    /**     * 属性信息     */    private final String name;  // 属性名    private final Object value; // 属性值        // bd的class对应的文件位置    private Object source;            /**     * 构造器(设置属性信息)     */    public BeanMetadataAttribute(String name, Object value) {        Assert.notNull(name, "Name must not be null");        this.name = name;        this.value = value;   }    /**     * 获取属性名、属性值以及获取、设置属性所属对象     */    public String getName() {        return this.name;   }    public Object getValue() {        return this.value;   }    public void setSource(Object source) {        this.source = source;   }    @Override    public Object getSource() {        return this.source;   }    /**     * 判断属性是否相等     */    @Override    public boolean equals(Object other) {        if (this == other) {            return true;       }        if (!(other instanceof BeanMetadataAttribute)) {            return false;       }        BeanMetadataAttribute otherMa = (BeanMetadataAttribute) other;        return (this.name.equals(otherMa.name) &&                ObjectUtils.nullSafeEquals(this.value, otherMa.value) &&                ObjectUtils.nullSafeEquals(this.source, otherMa.source));   }    @Override    public int hashCode() {        return this.name.hashCode() * 29 + ObjectUtils.nullSafeHashCode(this.value);   }    @Override    public String toString() {        return "metadata attribute '" + this.name + "'";   } }

至此,我们讲完了BeanDefinition接口、父接口、父接口实现类的源代码,BeanDefinition的实现类会继承BeanDefinition父接口的实现类。到此为止,BeanDefinition的实现类可以操作属性和源,下面讲解BeanDefinition的实现类如何实现BeanDefinition接口。

总结

 

kotlin

复制代码

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement

 

vbnet

复制代码

BeanDefinition接口的父接口: 1. AttributeAccessor         1.1 实现类AttributeAccessorSupport是1个抽象类,作用是操作bd的属性,属性存放在LinkedHashMap。 1.2 LinkedHashMap的key是String,value是BeanMetadataAttribute。 2. BeanMetadataElement         2.1 实现类BeanMetadataAttributeAccessor,作用是获取源即bd对应的class的磁盘文件位置 2.2 实现类BeanMetadataAttributeAccessor继承了AttributeAccessorSupport既可以操作属性值,也可以操作源         2.3 通过重写AttributeAccessorSupport抽象类的方法和BeanMetadataAttribute对象操作bd的属性。 ***/

一句话总结:BeanDefinition实现类BeanMetadataAttributeAccessor实现了BeanMetadataElement继承了AttributeAccessorSupport。既可以设置和获取源,也可以设置和获取bd的属性值。

作者:Emanon
链接:https://juejin.cn/post/7234909292447744037
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值