深入理解Spring的BeanDefinition体系

BeanDefinition是什么?

BeanDefinition通过翻译字面意思是Bean的定义,那么什么是Bean定义呢?我们知道spring的启动过程其实就是去把需要被spring管理的类创建出对应的实例,然后再把实例经过一系列的spring生命周期最后成为了bean,在这个过程中需要先收集到这个类的一些属性信息才能完成这整个过程,而这些类的属性信息(也就是对这个类的一些定义信息)就是BeanDefinition

BeanDefinition体系继承图

先看BeanDefinition的继承类图

单纯地看BeanDefinition的体系,可以看到有一个BeanDefinition的顶层接口,然后下面就是对这个BeanDefinition接口的一个抽象的实现AbstractBeanDefinition,在AbstractBeanDefinition下面就有多种实现了,这几个实现具体各自的实现是什么?下面我们会细说。但是我们现在先来看的是在BeanDefinition体系上面还有几个接口和实现类,这几个接口和实现类是干什么的呢?其实我们上面也说了BeanDefinition是对类的一个定义描述,除了它自身自带的一些定义类的属性之外,它还能去携带自定义的一些属性key-value,而这几个接口和实现类就是去承接这些自定义属性的作用 

BeanDefinition自定义额外属性的实现 

(1)AtttibuteAccessor

/**
 * 该接口定义了用于向任意对象附加和访问额外属性的方法规范(例如向BeanDefinition设置额外属性等)
 */
public interface AttributeAccessor {

   void setAttribute(String name, @Nullable Object value);

   @Nullable
   Object setAttributesetAttribute(String name);

   @Nullable
   Object removeAttribute(String name);

   boolean hasAttribute(String name);

   String[] attributeNames();
}

该接口由BeanDefinition接口直接实现,并且定义了添加属性setAttribute,获取属性setAttribute,移除属性removeAttribute,是否存在指定属性hasAttribute,获取所有的属性名称attributeNames,也就是说这个接口其实就是去定义自定义的属性并且去操作它们的,但是这里注意的是AttributeAccessor接口的实现并不是直接在BeanDefinition体系中实现的,通过上面的继承图可以知道,它是在AttributeAccessorSupport这个类中进行实现的,然后这个类由BeanDefinition体系进行继承,也就是BeanDefinition体系间接实现AttributeAccessor这个接口

(2)AttributeAccessorSupport

/**
 * 实现{@link AttributeAccessor}接口,提供它所有方法的基本实现,这里具体使用一个map对这些额外属性进行存储
 */
@SuppressWarnings("serial")
public abstract class AttributeAccessorSupport implements AttributeAccessor, Serializable {

   /**
    * 使用一个map去存储额外属性的key-value
    */
   private final Map<String, Object> attributes = new LinkedHashMap<>();


   @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);
      }
   }

   @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());
   }
   
   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));
      }
   }

   @Override
   public boolean equals(@Nullable Object other) {
      return (this == other || (other instanceof AttributeAccessorSupport &&
            this.attributes.equals(((AttributeAccessorSupport) other).attributes)));
   }

   @Override
   public int hashCode() {
      return this.attributes.hashCode();
   }

}

AttributeAccessorSupport这个类直接实现了AttributeAccessor接口,具体使用了一个map去存储自定义的属性key-value,而实现的AttributeAccessor接口的方法就是对基于这个map去操作的

(3)BeanMetadataAttributeAccessor

**
 * 继承了AttributeAccessorSupport,重写了{@link org.springframework.core.AttributeAccessorSupport}的对额外属性操作的方法,
 * 对额外属性的key和value进行封装,具体将属性保存为{@link BeanMetadataAttribute}对象
 */
@SuppressWarnings("serial")
public class BeanMetadataAttributeAccessor extends AttributeAccessorSupport implements BeanMetadataElement {

   /**
    * 该bean所对应的class文件
    */
   @Nullable
   private Object source;

   public void setSource(@Nullable Object source) {
      this.source = source;
   }

   @Override
   @Nullable
   public Object getSource() {
      return this.source;
   }

   public void addMetadataAttribute(BeanMetadataAttribute attribute) {
      super.setAttribute(attribute.getName(), attribute);
   }
   
   @Nullable
   public BeanMetadataAttribute getMetadataAttribute(String name) {
      return (BeanMetadataAttribute) super.getAttribute(name);
   }

   @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被BeanDefinition体系直接继承,同时它又继承了AttributeAccessorSupport,它对AttributeAccessorSupport中操作自定义属性的那几个方法进行了重写,重写之后的逻辑变成了把key-value都封装成一个BeanMetadataAttribute对象作为value,key不变,然后放到AttributeAccessorSupport的map中。这里还有一个点也要注意,就是BeanMetadataAttributeAccessor它还实现了BeanMetadataElement接口

public interface BeanMetadataElement {

   @Nullable
   default Object getSource() {
      return null;
   }

}

这个接口只有一个getSource方法,对于BeanDefinition体系来说,这个getSource具体返回的是这个BeanDefinition实例所对应的class文件资源

BeanDefinition体系中的分类

(1)BeanDefinition接口

在BeanDefinition接口中其实就是去定义了一些setXXX,getXXX的这些方法,这些方法就是去获取或者设置具体的某个属性定义值的

(2)AbstractBeanDefinition 

AbstractBeanDefinition直接继承于BeanDefinition接口,它分解出RootBeanDefinition,ChildBeanDefinition,GenericBeanDefinition的公共bean定义(继承图可以看出这三个BeanDefinition都是直接继承于AbstractBeanDefinition)

(3)RootBeanDefinition

 RootBeanDefinition通过字面意思来看表示一个根节点的BeanDefinition,因为BeanDefinition之间是可以通过设置继承关系的(在xml模式中的通过parent属性进行配置),在spring实例化bean阶段的时候会去把这些有继承关系的BeanDefinition进行合并,最终合并出一个新的RootBeaDefinition(就算没有继承关系的BeanDefinition也要去转化成RootDefinition),也就是说在spring实例化阶段都是围绕RootBeanDefinition去进行的(需要注意的是RootBeanDefinition不能去继承其他BeanDefinition)

(4)ChildBeanDefinition

ChildBeanDefinition它不能被单独使用,而是要用来配合RootBeanDefinition去使用,它在继承AbstractBeanDefinition的基础上只定义了一个parentName字段,表示当前这个ChildBeanDefinition继承于哪一个BeanDefinition。但是从spring2.5开始,ChildBeandefinition就被废弃了,取而代之的是GenericBeanDefinition 

(5)GenericBeanDefinition 

GenericBeanDefinition在spring2.5之后就取代了ChildBeanDefinition,它与ChildBeanDefnition不一样的是它能够单独去使用,不一定非要去继承某一个BeanDefinition 

(6)ScannedGenericBeanDefinition 

ScannedGenericBeanDefinition与上面的三个BeanDefinition不一样,它是继承于GenericBeanDefinition的。ScannedGenericBeanDefinition通过字面意思来看表示这个BeanDefinition是通过包扫描的方式去得到的,在ScannedGenericBeanDefinition中有一个AnnotationMetadata类型的属性,通过这个属性可以获取到这个BeanDefinition所对应的class文件的任何信息(比如注解,方法等等,底层是通过ASM去获取)

(7)AnnotatedGenericBeanDefinition 

AnnotatedGenericBeanDefinition也是继承于GenericBenaDefinition,它的作用其实和ScannedGenericBeanDefinition差不多,不同的是ScannedGenericBeanDefinition可以清晰地表示它是由包扫描的方式去获取到的,还有就是ScannedGenericBeanDefinition是通过ASM机制去获取class信息的,而AnnotatedGenericBeanDefinition不仅能够支持通过ASM去获取class信息,还能通过反射自省的方式去获取 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值