IOC之解析bean标签:BeanDefinition

2020-01-09 Spring 《Spring源码分析》

本文作者:chenssy

出处:http://cmsblogs.com/?p=2736

在学习Spring源码的过程中发现的好站+好贴,感谢作者。Spring版本:Spring 5.0.6.RELEASE


BeanDefinition

BeanDefinition 是一个接口,它描述了一个 Bean 实例,包括属性值、构造方法值和继承自它的类的更多信息。

代码如下:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

    String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;

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


    // Read-only attributes

    boolean isSingleton();

    boolean isPrototype();

    boolean isAbstract();

    int getRole();

    @Nullable
    String getDescription();

    @Nullable
    String getResourceDescription();

    @Nullable
    BeanDefinition getOriginatingBeanDefinition();

}

父类

BeanDefinition继承 AttributeAccessorBeanMetadataElement 接口。两个接口定义如下:

  • AttributeAccessor :定义了与其它对象的(元数据)进行连接和访问的约定,即对属性的修改,包括获取、设置、删除。

    代码如下:

    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();
    
    }
  • BeanMetadataElementBean 元对象持有的配置元素可以通过getSource() 方法来获取。

    代码如下:

    public interface BeanMetadataElement {
    
        @Nullable
        Object getSource();
    
    }

子类

BeanDefinition 整个结构如下图:

SIcYke

我们常用的三个实现类有:ChildBeanDefinitionGenericBeanDefinitionRootBeanDefinition,三者都继承 AbstractBeanDefinition。如果配置文件中定义了 ,则父 用 RootBeanDefinition表示,子 用 ChildBeanDefinition 表示,而没有父的就使用RootBeanDefinition 表示。GenericBeanDefinition 为一站式服务类。AbstractBeanDefinition对三个子类共同的类信息进行抽象。

解析 Bean 标签

BeanDefinitionParserDelegate.parseBeanDefinitionElement() 中完成 Bean 的解析,返回的是一个已经完成对 标签解析的 BeanDefinition 实例。

createBeanDefinition

在该方法内部,首先调用 createBeanDefinition() 方法创建一个用于承载属性的 GenericBeanDefinition 实例,如下:

protected AbstractBeanDefinition createBeanDefinition(
  @Nullable String className, @Nullable String parentName)
  throws ClassNotFoundException {
  return BeanDefinitionReaderUtils.createBeanDefinition(
    parentName, className, this.readerContext.getBeanClassLoader());
}

委托 BeanDefinitionReaderUtils 创建,如下:

public static AbstractBeanDefinition createBeanDefinition(
  @Nullable String parentName, 
  @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {

  GenericBeanDefinition bd = new GenericBeanDefinition();
  bd.setParentName(parentName);
  if (className != null) {
    if (classLoader != null) {
      bd.setBeanClass(ClassUtils.forName(className, classLoader));
    }
    else {
      bd.setBeanClassName(className);
    }
  }
  return bd;
}

该方法主要是设置 parentNameclassNameclassLoader

parseBeanDefinitionAttributes

创建完 GenericBeanDefinition 实例后,再调用 parseBeanDefinitionAttributes() ,该方法将创建好的 GenericBeanDefinition 实例当做参数,对 Bean 标签的所有属性进行解析,如下:

public AbstractBeanDefinition parseBeanDefinitionAttributes(
  Element ele, String beanName,
  @Nullable BeanDefinition containingBean,
  AbstractBeanDefinition bd) {
  // 解析 scope 标签
  if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
    error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
  }
  else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
    bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
  }
  else if (containingBean != null) {
    // Take default from containing bean in case of an inner bean definition.
    bd.setScope(containingBean.getScope());
  }

  // 解析 abstract 标签
  if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
    bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
  }

  // 解析 lazy-init 标签
  String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
  if (DEFAULT_VALUE.equals(lazyInit)) {
    lazyInit = this.defaults.getLazyInit();
  }
  bd.setLazyInit(TRUE_VALUE.equals(lazyInit));

  // 解析 autowire 标签
  String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
  bd.setAutowireMode(getAutowireMode(autowire));

  // 解析 depends-on 标签
  if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
    String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
    bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
  }

  // 解析 autowire-candidate 标签
  String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
  if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) {
    String candidatePattern = this.defaults.getAutowireCandidates();
    if (candidatePattern != null) {
      String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
      bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
    }
  }
  else {
    bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
  }

  // 解析 primay 标签
  if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
    bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
  }

  // 解析 init-method 标签
  if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
    String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
    bd.setInitMethodName(initMethodName);
  }
  else if (this.defaults.getInitMethod() != null) {
    bd.setInitMethodName(this.defaults.getInitMethod());
    bd.setEnforceInitMethod(false);
  }

  // 解析 destroy-mothod 标签
  if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
    String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
    bd.setDestroyMethodName(destroyMethodName);
  }
  else if (this.defaults.getDestroyMethod() != null) {
    bd.setDestroyMethodName(this.defaults.getDestroyMethod());
    bd.setEnforceDestroyMethod(false);
  }

  // 解析 factory-method 标签
  if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
    bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
  }
  if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
    bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
  }

  return bd;
}

从上面代码我们可以清晰地看到对 Bean 标签属性的解析,这些属性我们在工作中都或多或少用到过。 完成 Bean 标签基本属性解析后,会依次调用 parseMetaElements()parseLookupOverrideSubElements()parseReplacedMethodSubElements() 对子元素 metalookup-methodreplace-method 完成解析。下篇博文将会对这三个子元素进行详细说明。

Spring 死磕Spring

相关推荐



版权声明




文章目录