1:写在前面
本文,在spring是如何解析自定义标签的
这篇文章的基础上继续分析。另外注意,本文并不是在自定义标签基础上来分析BeanDefinition的注册,只是为了完整性,承接上文来分析,分析的还是默认命名空间下的bean注册。
2:回顾
在方法org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#processBeanDefinition
中就是进行BeanDefinition的解析和注册的,其中解析部分,我们已经在前面的文章中进行了分析,看下源码:
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#processBeanDefinition
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 解析默认命名空间
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// 使用bean的自定义子标签装饰,即解析自定义bean的子标签
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// <2021-03-08 21:17>
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// 触发注册完成事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
<2021-03-08 21:17>
处就是注册BeanDefinition的位置,具体参考3:registerBeanDefinition
。
3:registerBeanDefinition
org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerBeanDefinition
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// <2021-03-09 06:56>
// 获取bean名称
String beanName = definitionHolder.getBeanName();
// <2021-03-09 15:23>
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 获取别名数组
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
// <2021-03-09 15:24>
registry.registerAlias(beanName, alias);
}
}
}
<2021-03-09 06:56>
获取bean名称,关于bean名称规则不清楚的可以参考spring解析bean标签过程分析
。<2021-03-09 15:23>
是注册bean名称和bean定义的映射关系,详细参考3.1:注册bean名称
,<2021-03-09 15:24>
处是注册别名和bean名称的映射,详细参考3.2:注册别名和bean名称的映射
。
3.1:注册bean名称
源码:
org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
// 校验,不影响主逻辑,可忽略
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
// <2021-03-09 15:30>
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
// 如果是已存在
if (existingDefinition != null) {
// 存在并且不允许覆盖,则异常
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
// 已存在的bean定义优先级没有新的bean定义的高,
// 则打印日志,说明要覆盖了,这里一般是系统的覆盖用户定义的
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
// 单纯的不是相同bean定义,覆盖,并打印日志
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
// 到这里说明是相同的bean定义,打印相关日志
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
// 使用新的bean定义覆盖老的bean定义
this.beanDefinitionMap.put(beanName, beanDefinition);
}
// 如果是不存在
else {
// 如果已经开启bean创建,我们可以认为这里就是false
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
// 存放bean名称和bean定义映射信息到缓存中
this.beanDefinitionMap.put(beanName, beanDefinition);
// 所有注册的bean的名称,和beanDefinitionMap的key是对应的
this.beanDefinitionNames.add(beanName);
// 这里最终就是从org.springframework.beans.factory.support.DefaultListableBeanFactory#manualSingletonNames
// 中删除beanName,有什么用处我还不知道!
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
// 这里不很清楚是做啥的,可以认为是false
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}
<2021-03-09 15:30>
是通过bean名称从缓存中获取beandefinition,这里的缓存其实就是一个map,定义如下:
/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap
= new ConcurrentHashMap<>(256);
3.2:注册别名和bean名称的映射
源码:
org.springframework.core.SimpleAliasRegistry#registerAlias
public void registerAlias(String name, String alias) {
Assert.hasText(name, "'name' must not be empty");
Assert.hasText(alias, "'alias' must not be empty");
// <2021-03-09 15:53>
synchronized (this.aliasMap) {
// 如果是name和alias一样,则不需要映射,直接删除
if (alias.equals(name)) {
this.aliasMap.remove(alias);
if (logger.isDebugEnabled()) {
logger.debug("Alias definition '" + alias + "' ignored since it points to same name");
}
}
else {
// 通过别名获取已注册的bean名称
String registeredName = this.aliasMap.get(alias);
// 如果是存在已经注册的bean名称
if (registeredName != null) {
// 如果是已经注册的bean名称和当前需要注册的bean名称
// 相等,则说明已经注册过了,直接return
if (registeredName.equals(name)) {
// An existing alias - no need to re-register
return;
}
// 如果是已经注册bean名称不为空,并且不允许别名覆盖,则异常
if (!allowAliasOverriding()) {
throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" +
name + "': It is already registered for name '" + registeredName + "'.");
}
if (logger.isDebugEnabled()) {
logger.debug("Overriding alias '" + alias + "' definition for registered name '" +
registeredName + "' with new target name '" + name + "'");
}
}
// <2021-03-09 16:04>,循环检测
checkForAliasCircle(name, alias);
// 存放别名和bean名称对应关系到map中
this.aliasMap.put(alias, name);
if (logger.isTraceEnabled()) {
logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");
}
}
}
}
<2021-03-09 15:53>
处做一个并发处理,aliasMap存储的是别名->bean名称
的映射,定义如下:
/** Map from alias to canonical name. */
private final Map<String, String> aliasMap
= new ConcurrentHashMap<>(16);
<2021-03-09 16:04>
是检测循环,如下:
org.springframework.core.SimpleAliasRegistry#checkForAliasCircle
protected void checkForAliasCircle(String name, String alias) {
// <2021-03-09 16:05>
if (hasAlias(alias, name)) {
throw new IllegalStateException("Cannot register alias '" + alias +
"' for name '" + name + "': Circular reference - '" +
name + "' is a direct or indirect alias for '" + alias + "' already");
}
}
使用<2021-03-09 16:05>
处方法判断,比如当前存在(user1->user3)
,user2->user1
,如果是新加入的为(user3->user2)
则就死循环了,正常这种情况不会执行到这里,因为在方法org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#checkNameUniqueness
中已经对名称的唯一性做了检测了,如果存在重复就异常了,这里贴下源码,如下:
org.springframework.core.SimpleAliasRegistry#hasAlias
public boolean hasAlias(String name, String alias) {
// 循环已存在的别名->bean名称的映射关系
for (Map.Entry<String, String> entry : this.aliasMap.entrySet()) {
// 获取bean名称
String registeredName = entry.getValue();
if (registeredName.equals(name)) {
String registeredAlias = entry.getKey();
if (registeredAlias.equals(alias) || hasAlias(registeredAlias, alias)) {
return true;
}
}
}
// 最终说明不存在循环依赖,返回false
return false;
}
到这里,我们已经成功注册bean定义信息到spring中了,接下里就是通过这些bean定义来初始化spring bean了
,关于这部分内容参考spring使用bean定义初始化bean分析。