BeanDefinitionHolder顾名思义就是对BeanDefinition的持有,同时持有的包括BeanDefinition的名称和别名,BeanDefinition我们在前面的文章已经介绍过Spring源码分析-IOC之BeanDefinition,BeanDefinitionHolder同时实现了BeanMetadataElement,BeanMetadataElement我们在前面也已经介绍过Spring源码分析-IOC之BeanMetadataElement,有兴趣的同学可以看下,下面我们先看下BeanDefinitionHolder的源码:
//实现了BeanMetadataElement接口
public class BeanDefinitionHolder implements BeanMetadataElement {
//持有BeanDefinition
private final BeanDefinition beanDefinition;
//BeanDefinition的名称
private final String beanName;
//BeanDefinition的别名
//Nullable注解表示该属性可以为空
@Nullable
private final String[] aliases;
//根据bean的名称和beanDefinition初始化BeanDefinitionHolder
public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName) {
//此次实际是调用的另外一个构造方法
this(beanDefinition, beanName, null);
}
//根据bean的名称和beanDefinition,别名aliases初始化BeanDefinitionHolder
//别名aliases可以为空
public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName, @Nullable String[] aliases) {
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
Assert.notNull(beanName, "Bean name must not be null");
this.beanDefinition = beanDefinition;
this.beanName = beanName;
this.aliases = aliases;
}
//根据指定的BeanDefinitionHolder 复制一个新的BeanDefinitionHolder
//此处不是深克隆
public BeanDefinitionHolder(BeanDefinitionHolder beanDefinitionHolder) {
Assert.notNull(beanDefinitionHolder, "BeanDefinitionHolder must not be null");
this.beanDefinition = beanDefinitionHolder.getBeanDefinition();
this.beanName = beanDefinitionHolder.getBeanName();
this.aliases = beanDefinitionHolder.getAliases();
}
//获取BeanDefinition
public BeanDefinition getBeanDefinition() {
return this.beanDefinition;
}
//获取bean的名称
public String getBeanName() {
return this.beanName;
}
//获取别名
@Nullable
public String[] getAliases() {
return this.aliases;
}
//获取beanDefinition的源对象,实现了BeanMetadataElement
@Override
@Nullable
public Object getSource() {
return this.beanDefinition.getSource();
}
//判断指定的名称与beanName或者别名身份匹配
public boolean matchesName(@Nullable String candidateName) {
return (candidateName != null && (candidateName.equals(this.beanName) ||
candidateName.equals(BeanFactoryUtils.transformedBeanName(this.beanName)) ||
ObjectUtils.containsElement(this.aliases, candidateName)));
}
//返回一个描述包括bean的名称和所有的别名
public String getShortDescription() {
StringBuilder sb = new StringBuilder();
sb.append("Bean definition with name '").append(this.beanName).append("'");
if (this.aliases != null) {
sb.append(" and aliases [").append(StringUtils.arrayToCommaDelimitedString(this.aliases)).append("]");
}
return sb.toString();
}
//返回一个长描述包括名称,别名已经beanDefinition的内容
public String getLongDescription() {
StringBuilder sb = new StringBuilder(getShortDescription());
sb.append(": ").append(this.beanDefinition);
return sb.toString();
}
//重写toString方法
@Override
public String toString() {
return getLongDescription();
}
//重写equals方法
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof BeanDefinitionHolder)) {
return false;
}
BeanDefinitionHolder otherHolder = (BeanDefinitionHolder) other;
return this.beanDefinition.equals(otherHolder.beanDefinition) &&
this.beanName.equals(otherHolder.beanName) &&
ObjectUtils.nullSafeEquals(this.aliases, otherHolder.aliases);
}
//重写hashCode方法
@Override
public int hashCode() {
int hashCode = this.beanDefinition.hashCode();
hashCode = 29 * hashCode + this.beanName.hashCode();
hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.aliases);
return hashCode;
}
}
下面我们继续看BeanDefinitionHolder在spring中的应用,DefaultBeanDefinitionDocumentReader中在解析默认的标签bean元素的时候 :
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
//此处解析bean元素
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
接下来processBeanDefinition方法:
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//根据bean元素创建BeanDefinitionHolder
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
继续往下看BeanDefinitionParserDelegate中的parseBeanDefinitionElement:
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
String id = ele.getAttribute(ID_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isTraceEnabled()) {
logger.trace("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
//解析bean元素的属性,创建beanDefinition
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
beanName = this.readerContext.generateBeanName(beanDefinition);
// Register an alias for the plain bean class name, if still possible,
// if the generator returned the class name plus a suffix.
// This is expected for Spring 1.2/2.0 backwards compatibility.
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (logger.isTraceEnabled()) {
logger.trace("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
//创建一个BeanDefinitionHolder对象
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
以上方法实际上就是解析bean元素,创建beanDefinition,然后将beanDefinition,beanName,aliases创建为BeanDefinitionHolder,我们继续回到processBeanDefinition方法中:
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 根据BeanDefinitionHolder 注册beanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
//此处根据BeanDefinitionHolder 创建一个BeanComponentDefinition
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
我们继续看下BeanDefinitionReaderUtils.registerBeanDefinition的方法:
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// 就是根据BeanDefinitionHolder 的属性注册
//注册的具体内容细节我们将会在后面将
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
以上就是BeanDefinitionHolder 在spring的主要功能。
小结:我们在开发中也可以借鉴BeanDefinitionHolder 这种方式,更好的封装我们的数据。