1.美图
# 2.概述
BeanDefinitionHolder顾名思义就是对BeanDefinition的持有,同时持有的包括BeanDefinition的名称和别名,BeanDefinitionHolder同时实现了BeanMetadataElement,BeanMetadataElement
3.源码
//实现了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元素的时候 :
/**
* 使用Spring的Bean规则解析Document元素节点
* @param ele
* @param delegate
*/
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
//如果元素节点是<Import>导入元素,进行导入解析
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
//如果元素节点是<Alias>别名元素,进行别名解析
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
//元素节点既不是导入元素,也不是别名元素,即普通的<Bean>元素,
//按照Spring的Bean规则解析元素
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
接下来processBeanDefinition方法:
/**
* Process the given bean element, parsing the bean definition
* and registering it with the registry.
*
* 解析Bean定义资源Document对象的普通元素
*/
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// BeanDefinitionHolder是对BeanDefinition的封装,即Bean定义的封装类
//对Document对象中<Bean>元素的解析由BeanDefinitionParserDelegate实现
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// 2、装饰BeanDefinition
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
//向Spring IOC容器注册解析得到的Bean定义,这是Bean定义向IOC容器注册的入口,执行注册
// TODO: 向IOC中注册该BeanDefiniton
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
//在完成向Spring IOC容器注册解析得到的Bean定义之后,发送注册事件,发送一个BeanDefinition注册事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
继续往下看BeanDefinitionParserDelegate中的parseBeanDefinitionElement:
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
/**
* Parses the supplied {@code <bean>} element. May return {@code null}
* if there were errors during parse. Errors are reported to the
* {@link org.springframework.beans.factory.parsing.ProblemReporter}.
*
* 解析Bean定义资源文件中的<Bean>元素,这个方法中主要处理<Bean>元素的id,name和别名属性
*/
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
//获取<Bean>元素中的id属性值
String id = ele.getAttribute(ID_ATTRIBUTE);
//获取<Bean>元素中的name属性值
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
//获取<Bean>元素中的alias属性值
List<String> aliases = new ArrayList<>();
//将<Bean>元素中的所有name属性值存放到别名中
//如果name属性值不为空,按照 ,; 符号切分name,切分成一个name属性,并放入到aliases中
//这里看出bean的定义,可以定义多个name值,只要通过逗号或者分号分隔即可。
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
//把beanName设置成id,
String beanName = id;
//如果<Bean>元素中没有配置id属性时,将别名中的第一个值赋值给beanName
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");
}
}
//检查<Bean>元素所配置的id或者name的唯一性,containingBean标识<Bean>
//元素中是否包含子<Bean>元素
//如果传入的containingBean为null,就检验beanName和aliases是不是已经被占用了,
//占用了就抛出一个异常BeanDefinitionParsingException,
//这里传入的containingBean就是null,所以一定要经过里面检查
if (containingBean == null) {
//检查<Bean>元素所配置的id、name或者别名是否重复
checkNameUniqueness(beanName, aliases, ele);
}
//详细对<Bean>元素中配置的Bean定义进行解析的地方
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
//如果<Bean>元素中没有配置id、别名或者name,且没有包含子元素
//<Bean>元素,为解析的Bean生成一个唯一beanName并注册
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
//如果<Bean>元素中没有配置id、别名或者name,且包含了子元素<Bean>元素,为解析的Bean使用别名向IOC容器注册
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.
//为解析的Bean使用别名注册时,为了向后兼容 Spring1.2/2.0,给别名添加类名后缀
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);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
//当解析出错时,返回null
return null;
}
我们继续看下BeanDefinitionReaderUtils.registerBeanDefinition的方法:
/**
* Register the given bean definition with the given bean factory.
* @param definitionHolder the bean definition including name and aliases
* @param registry the bean factory to register with
* @throws BeanDefinitionStoreException if registration failed
*
* 将解析的BeanDefinitionHold注册到容器中
*/
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
//获取解析的BeanDefinition的名称
String beanName = definitionHolder.getBeanName();
//向IOC容器注册BeanDefinition
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
//如果解析的BeanDefinition有别名,向容器为其注册别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
以上就是BeanDefinitionHolder 在spring的主要功能。