spring BeanDefinition加载过程(xml)

注:1.本文内容不是很细致,只能帮助大家了解个大概流程-_-||
2.方法里会删减无关的内容

spring beanDefinition加载,在方法obtainFreshBeanFactory中完成在这里插入图片描述
在这里插入图片描述
refreshBeanFactory方法
在这里插入图片描述createBeanFactory:创建容器,会获取parent容器作为参数传入
在这里插入图片描述
在这里插入图片描述

loadBeanDefinition:先创建beanDefinitionReader
在这里插入图片描述
获取resource,也就是配置的xml文件
在这里插入图片描述
将resource读入,解析成document对象
在这里插入图片描述
主要方法在这,传入doc节点,开始解析
在这里插入图片描述
parseDefaultElement方法解析标签import、alias、bean、beans四种
在这里插入图片描述

import解析

获取标签中resource的值,会根据location是否是绝对路径,走不同的分支。
将location解析为resource后,递归对该resource执行loadBeanDefinitions方法,

	protected void importBeanDefinitionResource(Element ele) {
		String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
		location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
		boolean absoluteLocation = false;
		absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
		if (absoluteLocation) {
			int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
		}
		else {
				Resource relativeResource = getReaderContext().getResource().createRelative(location);
				if (relativeResource.exists()) {
					importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
					actualResources.add(relativeResource);
				}
				else {
					String baseLocation = getReaderContext().getResource().getURL().toString();
					importCount = getReaderContext().getReader().loadBeanDefinitions(
							StringUtils.applyRelativePath(baseLocation, location), actualResources);
				}
		}
		Resource[] actResArray = actualResources.toArray(new Resource[0]);
		getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
	}

alias解析

读取name、alias两个属性的值
在这里插入图片描述
1.如果alias和name相同,则aliasMap中移除这个alias。
2.根据alias查询aliasmap中是否已存在,已存在并且name相同则不再处理,已存在但name不同,则根据是否允许alias覆盖(allowAliasOverriding),来决定是否抛出异常。
3.检查name是否已经存在alias,存在则抛异常
在这里插入图片描述

bean标签解析

将元素转为BeanDefinitionHolder,注册beanDefinition
在这里插入图片描述
1.获取bean标签中的id、name属性的值
2.name不为空,则根据逗号、分号将name分割为数组
3.如果没有设置id,但是设置了name,会取第一个name作为beanName
4.检查beanName唯一性
5.parseBeanDefinitionElement方法会解析标签中的属性,并对beanDefinition进行赋值
6.beanName为空,则会产生一个,还会放入aliasmap。规则:class全路径名称+#+数字(从0开始自增,如果存在则继续下一个数字)

	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
		String id = ele.getAttribute(ID_ATTRIBUTE);
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
		List<String> aliases = new ArrayList<>();
		if (StringUtils.hasLength(nameAttr)) {
			String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			aliases.addAll(Arrays.asList(nameArr));
		}
		String beanName = id;
		if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
			beanName = aliases.remove(0);
		}
		if (containingBean == null) {
			checkNameUniqueness(beanName, aliases, ele);
		}
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
		if (beanDefinition != null) {
			if (!StringUtils.hasText(beanName)) {
				try {
					if (containingBean != null) {
						beanName = BeanDefinitionReaderUtils.generateBeanName(
								beanDefinition, this.readerContext.getRegistry(), true);
					}
					else {
						beanName = this.readerContext.generateBeanName(beanDefinition);
						String beanClassName = beanDefinition.getBeanClassName();
						if (beanClassName != null &&
								beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
								!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
							aliases.add(beanClassName);
						}
					}
				}
				catch (Exception ex) {
					error(ex.getMessage(), ele);
					return null;
				}
			}
			String[] aliasesArray = StringUtils.toStringArray(aliases);
			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
		}
		return null;
	}

beans标签解析

递归过程,不再描述
在这里插入图片描述
在这里插入图片描述
以上是parseDefaultElement解析过程,只解析标签beans、bean、alias、import四种

其余例如aop标签解析,则在下面方法中。
在这里插入图片描述
获取namespaceurl,也就是
在这里插入图片描述
根据namespaceurl找到相应的handler

在这里插入图片描述
再根据具体的标签名,找到parser
在这里插入图片描述
具体的解析过程都在parser的parse方法里,例如component-scan
先找base-package属性的值,
调用scan方法,先找出包下的所有类,再根据类上的注解@Component、@ManagedBean进行筛选,注册到容器中
在这里插入图片描述
其余标签解析也是这个流程,大家可以自行debug看看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值