文档章节

spring application 之 Xml解析

my_juke
 my_juke
发布于 06/09 11:30
字数 1023
阅读 11
收藏 1

org.springframework.beans.factory.xml.XmlBeanDefinitionReader

解析XML的入口类

DefaultBeanDefinitionDocumentReader

XML标签解析类

	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {
						parseDefaultElement(ele, delegate);
					}
					else {
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}

解析默认的beans标签

	private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

解析beans下的import标签

可以理解为递归调用,进行解析

<beans>
	<import resource="file://e:/a.xml"></import>
</beans>

解析beans下的alias标签

<bean>
	<alias name="a" alias="a1"></alias>
</bean>

解析beans下的beans标签

递归解析

<beans>
	<beans profile="dev"></beans>
</beans>

解析beans下的bean标签

	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}
<bean id="" name=""></bean>

优先用id,name作为别名
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
解析class,parent

<bean class="spring.A" parent="b"></bean>  

创建abstractBeanDefinition

`AbstractBeanDefinition bd = createBeanDefinition(className, parent);`  
public static AbstractBeanDefinition createBeanDefinition(
			@Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {

		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;
	}


BeanMetadataElement 描述某个对象上的元素据
AttributeAccessor获取与设置某个对象上的属性
AttributeAccessorSupportAttributeAccessor的抽象实现
BeanMetadataAttributeAccessorAttributeAccessorSupport的实现
BeanDefinition对像描述,主要有以下几个信息

void setParentName(@Nullable String parentName);
void setBeanClassName(@Nullable String beanClassName);
void setScope(@Nullable String scope);
void setLazyInit(boolean lazyInit);
void setDependsOn(@Nullable String... dependsOn);
void setAutowireCandidate(boolean autowireCandidate);
void setPrimary(boolean primary);
void setFactoryBeanName(@Nullable String factoryBeanName);
void setFactoryMethodName(@Nullable String factoryMethodName);
ConstructorArgumentValues getConstructorArgumentValues();
MutablePropertyValues getPropertyValues();

先通过className,parentName创建一个 GenericBeanDefinition

解析bean标签上的属性

parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
<bean scope="single" abstract="false" lazy-init="false" 
autowire="default" depends-on="" primary="true" init-method="init" 
destroy-method="close" factory-bean="" factory-method=""
>
</bean>

解析bean下面的meta标签

对Bean的扩充

parseMetaElements(ele, bd);

比如:ConfigurationClassPostProcessor 的先后顺序就有用到

	public static int getOrder(BeanDefinition beanDef) {
		Integer order = (Integer) beanDef.getAttribute(ORDER_ATTRIBUTE);
		return (order != null ? order : Ordered.LOWEST_PRECEDENCE);
	}

解析bean下的lookup-method标签

say方法是抽象的,必须是无参的并且返回值必须是b对象的类型。

<bean>
<lookup-method name="say" bean="b">
</lookup-method>
</bean>

解析bean下的replaced-method标签

say方法的名称,参数类型与顺序,参数个数,返回值类型必须与b对象的一致

<bean>
  <replaced-method name="say" replacer="b">
    <arg-type match="java.lang.String"></arg-type>
  </replaced-method>
</bean>

解析bean下的constructor-agr标签

构造参数注入 如果存在index属性,以下条件都符合要求,如果没有index,type或者name可能都需要

<bean>
  <constructor-arg index="1" ref="b"/>
  <constructor-arg index="2" value="b"/>
  <constructor-arg index="3">
    <bean></bean>
  </constructor-arg>
  <constructor-arg index="4">
    <ref bean="b"></ref>
  </constructor-arg>
  <constructor-arg index="5">
    <ref parent="b"></ref> //从父容器中获取
  </constructor-arg>
  <constructor-arg index="6">
    <idref bean="b"></idref> //返回bean的名称,而不是bean的对象
  </constructor-arg>
  <constructor-arg index="7">
    <value>b</value>
  </constructor-arg>
  <constructor-arg index="8">
  	<null></null>
  </constructor-arg>
  <constructor-arg index="9">
    <array value-type="java.lang.String">
	  //递归解析子标签
     </array>
  </constructor-arg>
  <constructor-arg index="10">
    <list>
	//递归解析子标签
    </list>
  </constructor-arg>
  <constructor-arg index="11">
    <set>
	//递归解析子标签
    </set>
  </constructor-arg>
  <constructor-arg index="12">
    <map>
	  //这里可以用key,key-ref value value-ref或者子标签
	  <entry key="b" value="b"></entry>
	  <entry key-ref="b" value-ref="b"></entry>
	  <entry>
	  	<key>子标签</key>
		<value>子标签</value>
	  </entry>
	</map>
  </constructor-arg>
  <constructor-arg index="13">
    <props>
	  <prop key="b">b</prop>
	</props>
  </constructor-arg>
</bean>

解析bean的property标签

<bean>
 <property name="a" ref=""></property>
 <property name="a" value=""></property>
 <property name="a">
   //子标签
 </property>
</bean>

解析bean的qualifier标签

<bean>
<qualifier type="xxx" value=""></qualifier>
</bean>

对beans下的bean进行装饰

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
			Element ele, BeanDefinitionHolder definitionHolder, @Nullable BeanDefinition containingBd) {

		BeanDefinitionHolder finalDefinition = definitionHolder;

		// Decorate based on custom attributes first.
		NamedNodeMap attributes = ele.getAttributes();
		for (int i = 0; i < attributes.getLength(); i++) {
			Node node = attributes.item(i);
			finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
		}

		// Decorate based on custom nested elements.
		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;
	}

装饰处理类配置在META-INF/spring.handlers

解析自定义标签

自定义标签处理类配置在META-INF/spring.handlers

BeanDefinitionValueResolver

子标签解析类

© 著作权归作者所有

my_juke
粉丝 4
博文 34
码字总数 22261
作品 0
深圳
私信 提问
Dubbo源码-Dubbo是如何随心所欲自定义XML标签的

叨叨 今天考虑了很久要不要写这篇文章。 距离《Dubbo源码》系列的开篇到现在已经快两个月时间了。当时是想着工作上的RPC框架使用存在一些让人头疼的问题,就来看看Dubbo给出了一套什么样的解...

Jackie_Zheng
2018/05/20
0
0
Spring Ioc 源码分析(二)- bean的实例化

在 Spring Ioc 源码分析(一)- XML 解析 中,我们完成了从 xml 到 BeanDefinition的过程。只是把 xml描述的 Bean定义转换为 Java对象描述。本文将讲解 spring 如何利用 BeanDefinition 完成...

我叫董先森
2017/10/19
20
0
在某某下,什么叫容器?一直困惑的问题

1.在spring里的容器,container指的是什么 applicationContext 就是所说的 container吗? 2容器指的就是 持有一个 map 或者list引用的 类吗? 3.tomcat里的容器 指的是什么? 4.假如自己写一...

mauersu
2013/04/03
293
7
Spring3 MVC Restful 多请求类型(json,xml,k-v),多视图配置(J...

beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="ht......

李长春
2011/09/15
1K
0
携程大佬带你写一个可扩展的Spring插件

# 背景介绍 Spring现在几乎已经成为了Java开发的必备框架,在享受Spring框架本身强大能力的同时,有时我们也会希望自己研发的组件和Spring进行整合,从而使得组件更易于上手,而且配合Sprin...

Java架构师CAT
08/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

springboot2.0 maven打包分离lib,resources

springboot将工程打包成jar包后,会出现获取classpath下的文件出现测试环境正常而生产环境文件找不到的问题,这是因为 1、在调试过程中,文件是真实存在于磁盘的某个目录。此时通过获取文件路...

陈俊凯
今天
6
0
BootStrap

一、BootStrap 简洁、直观、强悍的前端开发框架,让web开发更加迅速、简单 中文镜像网站:http://www.bootcss.com 用于开发响应式布局、移动设备优先的WEB项目 1、使用boot 创建文件夹,在文...

wytao1995
今天
10
0
小知识:讲述Linux命令别名与资源文件的区别

别名 别名是命令的快捷方式。为那些需要经常执行,但需要很长时间输入的长命令创建快捷方式很有用。语法是: alias ppp='ping www.baidu.com' 它们并不总是用来缩短长命令。重要的是,你将它...

老孟的Linux私房菜
今天
8
0
《JAVA核心知识》学习笔记(6. Spring 原理)-5

它是一个全面的、企业应用开发一站式的解决方案,贯穿表现层、业务层、持久层。但是 Spring 仍然可以和其他的框架无缝整合。 6.1.1. Spring 特点 6.1.1.1. 轻量级 6.1.1.2. 控制反转 6.1.1....

Shingfi
今天
8
0
Excel导入数据库数据+Excel导入网页数据【实时追踪】

1.Excel导入数据库数据:数据选项卡------>导入数据 2.Excel导入网页数据【实时追踪】:

东方墨天
今天
11
1

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部