spring源码深度解析(笔记二)--默认标签的解析

默认标签的解析是在parseDefaultElement中:

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele); //处理import标签
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);    //处理alias标签
		}
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);   //处理bean标签
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			doRegisterBeanDefinitions(ele);     //处理beans标签
		}
	}

分析对bean标签的解析及注册:

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
	BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
	if (bdHolder != null) {
		bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
		try {
			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));
	}
}

1,首先委托BeanDefinitionDelegate类的parseBeanDefinitionElement方法进行元素解析,返回BeanDefinitionHolder类实例bdHolder,此时bdHolder实例中已经包含了配置文件中的各种属性,如class、name、id、alias.

2,当返回的bdHolder不为空时,若存在默认标签的子节点下再有自定义属性,还需再次对自定义标签进行解析.

3,注册bdHolder

4,发出响应事件,通知相关的监听器,这个bean已经加载完成.


以下是每一步的具体分析(代码多有删减,只保留关键处):

===========================================================

一,返回包含各种配置属性的BeanDefinitionHolder实例bdHolder

public class BeanDefinitionParserDelegate {
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
		//解析id属性
		String id = ele.getAttribute(ID_ATTRIBUTE);
		//解析name属性
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
		//分隔name属性......
		
		//进一步解析其他属性并统一封装到GenericBeanDefinition类型的实例中
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
		
		//若检测到bean没有指定beanName,那么使用默认规则为此bean生成beanName
		if (containingBean != null) {
			beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);
		}
		else {
			beanName = this.readerContext.generateBeanName(beanDefinition);
			
		//将获取到的信息封装到BeanDefinitionHolder
		return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
	}

public class BeanDefinitionParserDelegate {
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {
	this.parseState.push(new BeanEntry(beanName));
	//解析class属性
	String className = null;
	if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
		className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
	}

	//解析parent属性
		String parent = null;
		if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
			parent = ele.getAttribute(PARENT_ATTRIBUTE);
		}
	//创建用于承载各种属性的AbstractBeanDefinition子类GenericBeanDefinition的实例
	AbstractBeanDefinition bd = createBeanDefinition(className, parent);

	//硬编码解析默认bean的各种属性
		parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
	//提取description
		bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

	//解析元数据
		parseMetaElements(ele, bd);
	//解析lookup-method属性
		parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
	//解析replaced-method属性
		parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
	//解析构造函数参数
		parseConstructorArgElements(ele, bd);
	//解析property子元素
		parsePropertyElements(ele, bd);
	//解析qualifier子元素
		parseQualifierElements(ele, bd);
		bd.setResource(this.readerContext.getResource());
		bd.setSource(extractSource(ele));
		return bd;



BeanDefinition是AbstractBeanDefinition的接口.

spring通过BeanDefinition将配置文件中的bean配置信息转换为容器的内部表示,并将这些BeanDefinition注册到BeanDefinitionRegistry中。

spring的BeanDefinitionRegistry就像是spring配置信息的内存数据库,主要是以map的形式保存;后续操作直接从BeanDefinitionRegistry中读取配置信息.

protected AbstractBeanDefinition createBeanDefinition(String className, String parentName) {
		return BeanDefinitionReaderUtils.createBeanDefinition(parentName, className, this.readerContext.getBeanClassLoader());
	}

public class BeanDefinitionReaderUtils {
public static AbstractBeanDefinition createBeanDefinition(String parentName, String className, ClassLoader classLoader) {

	GenericBeanDefinition bd = new GenericBeanDefinition();
	bd.setParentName(parentName);
	if (className != null) {
		if (classLoader != null) {
			bd.setBeanClass(ClassUtils.forName(className, classLoader));  //加载字节码文件
		}
		else {
			bd.setBeanClassName(className);
		}
	}
	return bd;
}

有了承载各种属性的BeanDefinition实例了,可以进行各种属性的解析了.

scope、singleton、abstract、lazy-init、autowire、dependency-check、depends-on、autowire-candidate、primary、init-method、destroy-method、factory-method、

factory-bean属性等.

meta属性用作额外的声明;

lookup-method获取器注入,把一个方法声明为返回某种类型的bean,但实际要返回的bean是在配置文件里面配置.

replace-method方法替换,可以在运行时用新的方法替换现有的方法.


=============================================

解析默认标签中的自定义类型属性:

public class BeanDefinitionParserDelegate {
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) {
	BeanDefinitionHolder finalDefinition = definitionHolder;
	NamedNodeMap attributes = ele.getAttributes();

	//遍历所有属性,看看是否有适用于修饰的属性
	for (int i = 0; i < attributes.getLength(); i++) {
		Node node = attributes.item(i);
		finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
	}

	NodeList children = ele.getChildNodes();
	//遍历所有的子节点,看看是否有适用于修饰的子元素
	for (int i = 0; i < children.getLength(); i++) {
		Node node = children.item(i);
		if (node.getNodeType() == Node.ELEMENT_NODE) {
			finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
		}
	}
	return finalDefinition;
}

public BeanDefinitionHolder decorateIfRequired(Node node, BeanDefinitionHolder originalDef, BeanDefinition containingBd) {
	//获得自定义标签的命名空间
	String namespaceUri = getNamespaceURI(node);
	//对于非默认标签的进行修饰
	if (!isDefaultNamespace(namespaceUri)) {
		//根据命名空间找到对应的处理器
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		if (handler != null) {
			//进行修饰
			return handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
		}
	}
	return originalDef;
}

====================================================

注册解析的BeanDefinition

BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());

public class BeanDefinitionReaderUtils {
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry){
	//使用beanName做唯一标识注册
	String beanName = definitionHolder.getBeanName();
	registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
	//注册所有别名
	String[] aliases = definitionHolder.getAliases();
	if (aliases != null) {
		for (String alias : aliases) {
			registry.registerAlias(beanName, alias);
		}
	}
}


private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
	if (beanDefinition instanceof AbstractBeanDefinition) {
		try {
			//注册前最后一次校验,校验methodOverrides
			((AbstractBeanDefinition) beanDefinition).validate();
		}
		catch (BeanDefinitionValidationException ex) {
			//抛异常
		}
	}

	//处理已经注册beanName的情况
	//记录beanName
	this.beanDefinitionNames.add(beanName);
	this.frozenBeanDefinitionNames = null;
	//注册beanDefinition
	this.beanDefinitionMap.put(beanName, beanDefinition);
	resetBeanDefinition(beanName); //重置所有beanName对应的缓存
}

public class SimpleAliasRegistry implements AliasRegistry {
private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
public void registerAlias(String name, String alias) {
	if (alias.equals(name)) {
		this.aliasMap.remove(alias); //若beanName与alias相同的话不记录alias,并删除对应的alias
	}
	else {
		String registeredName = this.aliasMap.get(alias);
		if (registeredName != null) {
			if (registeredName.equals(name)) {
				return;
			}
			if (!allowAliasOverriding()) {
			//若alias不允许被覆盖则抛异常
			}
		}
		checkForAliasCircle(name, alias);
		//注册alias
		this.aliasMap.put(alias, name);
	}
}

====================================================

通知监听器解析及注册完成

getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));

此实现只为扩展,当需要对注册BeanDefinition事件进行监听时,可以通过注册监听器的方式将处理逻辑写入监听器中.


=================================

=================================

alias、import及beans标签和bean标签的解析大同小异.



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值