Spring源码学习(八)---注册BeanDefinition

这里主要是使用org.springframework:spring-beans:5.2.0.RELEASE进行分析


1. 查看源码相关的快捷键

快捷键作用
Ctrl + Shift+i出现类似于预览的小窗口
Ctrl + Enter(接上步)完全打开源码
Ctrl + 鼠标左键一步到位打开源码 = Ctrl + Shift+i –>Ctrl + Enter
Alt+7查看类的有什么方法
ctrl+f12查看继承方法
ctrl+h查看接口的实现类
alt+7查看类的有什么方法
2下shift全局搜索整个项目

一 . 注册BeanDefinition

  1. 对配置文件解析完成后,注册BeanDefinition
    在这里插入图片描述

1. processBeanDefinition() 源码分析

//解析bean标签将其转换为definition并注册到BeanDefinitionRegistry
	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
	 1、将解析的节点信息封装至BeanDefinitionHolder对象
	 BeanDefinitionHolder-->封装了BeanDefinition,beanName以及aliases
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
		// 2、装饰BeanDefinition
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
			// 3、执行注册
		//这里是重点 进入注册BeanDefinition()中
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			  // 4、发送注册事件
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

在这里插入图片描述

进去 registerBeanDefinition()方法

2. registerBeanDefinition() 源码分析

	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		  // 1、注册BeanDefinition
		String beanName = definitionHolder.getBeanName();
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		  //  2、注册aliases(别名)
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}
	}

在这里插入图片描述

  1. 对于beanDefinition的注册分成了两部分:通过beanName的注册以及通过别名Aliases的注册。

1.beanName注册BeanDefinition

进去方法 registerBeanDefinition()
在这里插入图片描述

进去实现接口的方法

在这里插入图片描述

1. 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");
		// 如果beanDefinition是AbstractBeanDefinition实例,则验证
		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
			
 		   //验证不能将静态工厂方法与方法重写相结合(静态工厂方法必须创建实例)
          //主要是对于AbstractBeanDefinition属性中的methodOverrides校验,
          // 校验methodOverrides是否与工厂方法并存或者methodOverrides对应的方法根本不存在
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}
	// 尝试从缓存中加载BeanDefinition
		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		// beanName已经存在且不允许被覆盖,抛出异常
		if (existingDefinition != null) {
		// 如果对应的beanName已经注册且在配置中配置了bean不允许被覆盖,则抛出异常。
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
			}
		 // 使用新的BeanDefinition覆盖已经加载的BeanDefinition
			else if (existingDefinition.getRole() < beanDefinition.getRole()) {
			
				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 + "]");
				}
			}
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		//    缓存中无对应的BeanDefinition,则直接注册
		else {
		 如果beanDefinition已经被标记为创建
			if (hasBeanCreationStarted()) {
	
		// 因为beanDefinitionMap是全局变量,这里定会存在并发访问的情况
				synchronized (this.beanDefinitionMap) {
				 加入beanDefinitionMap
					this.beanDefinitionMap.put(beanName, beanDefinition);
					//  // 创建List<String>并将缓存的beanDefinitionNames和新解析的beanName加入集合
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
									updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
						 // 将updatedDefinitions赋值给beanDefinitionNames
					this.beanDefinitionNames = updatedDefinitions;
					  // 移除新注册的beanName
					removeManualSingletonName(beanName);
				}
			}
			else {
				 // 将beanDefinition信息维护至缓存
            // beanDefinitionMap-->(key->beanName,value->beanDefinition)
				this.beanDefinitionMap.put(beanName, beanDefinition);
				// beanDefinitionNames-->维护了beanName集合
				this.beanDefinitionNames.add(beanName);
				removeManualSingletonName(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

		if (existingDefinition != null || containsSingleton(beanName)) {
		 // 重置所有beanName对应的缓存
			resetBeanDefinition(beanName);
		}
	}
  1. 如果beanDefinition是AbstractBeanDefinition实例,则验证

  2. 校验methodOverrides是否与工厂方法并存或者methodOverrides对应的方法根本不存在

  3. 优先尝试从缓存中加载BeanDefinition

  4. 对beanName已经注册的情况的处理。如果设置了不允许bean的覆盖,则需要抛出异常,否则直接覆盖。

  5. 缓存中无对应的BeanDefinition,则直接注册

  6. 重置所有beanName对应的缓存

2. 别名Alias注册BeanDefinition

registerBeanDefinition() 中的registerAlias() 进去方法查看源码

在这里插入图片描述

再次进入实现类中的registerAlias() 方法

在这里插入图片描述
1. registerAlias() 方法源码分析

@Override
	public void registerAlias(String name, String alias) {
		Assert.hasText(name, "'name' must not be empty");
		Assert.hasText(alias, "'alias' must not be empty");
		synchronized (this.aliasMap) {
	// 如果beanName与别名相同
			if (alias.equals(name)) {
			  //移除别名
				this.aliasMap.remove(alias);
				if (logger.isDebugEnabled()) {
					logger.debug("Alias definition '" + alias + "' ignored since it points to same name");
				}
			}
			else {
			//尝试从缓存中获取别名
				String registeredName = this.aliasMap.get(alias);
				//如果别名已经在缓存中存在
				if (registeredName != null) {
				 //缓存中的别名和beanName(注意:不是别名)相同,不做任何操作,不需要再次注册
					if (registeredName.equals(name)) {
						return;
					}
					///缓存中存在别名,且不允许覆盖,抛出异常
					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 + "'");
					}
				}
		//检查给定名称是否已指向另一个方向的别名作为别名,预先捕获循环引用并抛出相应的IllegalStateException
				checkForAliasCircle(name, alias);
				//缓存别名
				this.aliasMap.put(alias, name);
				if (logger.isTraceEnabled()) {
					logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");
				}
			}
		}
	}

主要的过程

  1. 如果beanName与别名相同, 移除别名
  2. 尝试从缓存中获取别名
  3. 如果别名已经在缓存中存在
  4. 缓存中的别名和beanName相同,不做任何操作,不需要再次注册
  5. 缓存中存在别名,且不允许覆盖,抛出异常
  6. 检查给定名称是否已指向另一个方向的别名作为别名,预先捕获循环引用并抛出相应的IllegalStateException
  7. 缓存别名
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值