IOC之解析bean标签:BeanDefinition

本文作者: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 完成解析。下篇博文将会对这三个子元素进行详细说明。