SpringBoot 基础概念:注册BeanDefinition

SpringBoot 基础概念:注册BeanDefinition

    • 1. 前言
    • 2. BeanDefinitionReaderUtils#registerBeanDefinition
    • 3. DefaultListableBeanFactory#registerBeanDefinition

1. 前言

问题:为什么需要注册BeanDefinition?
为了后续实例化。Spring架构是将Bean的定义信息注册流程和Bean的实例化过程分开的。
BeanDefinition就是对Bean的定义的信息,包含了class等信息。

2. 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
 */
public static void registerBeanDefinition(
		BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
		throws BeanDefinitionStoreException {

	// Register bean definition under primary name.
	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);
		}
	}
}
  1. 该方法是注册BeanDefinition的工具方法。
  2. 参数:
    definitionHolder:是对BeanDefinition的封装,里面有beanName和aliases(bean的别名)。
    BeanDefinitiion:Bean的一些定义信息,包含class信息。
    registry:可以理解为DefaultListableBeanFactory。
  3. 将BeanDefinition注册到DefaultListableBeanFactory。将别名与beanName进行绑定,方便通过别名获取bean,别名与bean的名称是不能相互依赖的。

3. DefaultListableBeanFactory#registerBeanDefinition

@Override
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);
		}
	}

	BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
	if (existingDefinition != null) {
		//如果已经注册了BeanDefinition,那么就判断是否循序覆盖,不允许覆盖则抛出异常
		if (!isAllowBeanDefinitionOverriding()) {
			throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
		}
		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 + "]");
			}
		}
		else if (!beanDefinition.equals(existingDefinition)) {
			if (logger.isDebugEnabled()) {
				logger.debug("Overriding bean definition for bean '" + beanName +
						"' with a different definition: replacing [" + existingDefinition +
						"] with [" + beanDefinition + "]");
			}
		}
		else {
			if (logger.isTraceEnabled()) {
				logger.trace("Overriding bean definition for bean '" + beanName +
						"' with an equivalent definition: replacing [" + existingDefinition +
						"] with [" + beanDefinition + "]");
			}
		}
		//注册BeanDefinition
		this.beanDefinitionMap.put(beanName, beanDefinition);
	}
	else {
		//没有注册相同的BeanDefinition
		if (hasBeanCreationStarted()) {
			//已经开始了实例化Bean
			// Cannot modify startup-time collection elements anymore (for stable iteration)
			synchronized (this.beanDefinitionMap) {
				//使用了copyOnWrite原理,读写分离地去注册BeanDefinition
				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 {
			// Still in startup registration phase
			//如果依然在注册BeanDefinition的阶段,那么就直接去注册BeanDefinition
			this.beanDefinitionMap.put(beanName, beanDefinition);
			this.beanDefinitionNames.add(beanName);
			//移除了手动注册的单例名称
			removeManualSingletonName(beanName);
		}
		this.frozenBeanDefinitionNames = null;
	}

	//如果单例池中已经注册了相同的实例,那么就重置BeanDefinition
	if (existingDefinition != null || containsSingleton(beanName)) {
		resetBeanDefinition(beanName);
	}
}
  1. 如果已经注册了BeanDefinition,那么就判断是否循序覆盖,不允许覆盖则抛出异常。是否允许覆盖是在spring.main.allow-bean-definition-overriding配置,在SpringBoot启动流程中有讲解。
    SpringBoot 源码解析2:启动流程
  2. 如果已经该是实例化Bean的流程,那么就使用copyOnWrite原理注册BeanDefinition和beanName。因为Bean的实例化流程可能是用户多线程去getBean的,就会引发线程安全问题。
  3. 如果没有开始实例化流程,那么就直接注册BeanDefinition和BeanName。
  4. 移除了手动注册的beanName,Spring原则是优先使用用户配置,再使用内部默认配置。
  5. 如果单例池中已经注册了相同的实例,那么就重置BeanDefinition,即删除单例池中的对象,重新注册BeanDefinition,后续重新去实例化。

你可能感兴趣的:(spring,boot,java,后端)