Spring-IOC之BeanDefinitionHolder

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的主要功能。

发布了1089 篇原创文章 · 获赞 451 · 访问量 136万+

猜你喜欢

转载自blog.csdn.net/qq_21383435/article/details/104135232