spring IOC注册BeanDefinition

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分析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值