spring源码阅读(三)

接sping源码分析(二)

doLoadBeanDefinitions去解析 inputResoucre 和Resource 的具体实现:

这里解析 成Document 的操作主要是运用了 JDK自带的XML解析工具JAXP。同时还涉及 profile 以及 XML验证 DTD、XSD 的验证方法。
解析成document的操作:

这里 使用DocumentLoader 接口 来解析配置文件的 这里使用的是它的默认实现DefaultDocumentLoader

同时也涉及EntityResolver

DefalutDocumentLoader 解析document 的进一步操作:

这里是获取DocumentBuilderFactory

这里 使用了 XSD 的验证格式验证

这里是DocumentBuilder的生成:

这里普及一下JAXP的一些基本的知识:

Java API for XML(JAXP)

作用:解析XML文档的一套Java API,其为DOM和SAX两种解析机制提供了支持。

缺陷:使用繁琐,代码量大,可读性低。
解决方法:使用dom4j或JDOM解析器。

JAXP本身没有提供任何的XML解析支持,所以JAXP依赖与XML解析器,但其本身不与任何XML解析器耦合,因此可轻松在各种XML解析器直接切换而无须修改源代码,本质解释XML解析器与应用程序直接的抽象层。

JAXP由JDK直接提供,其包括:
javax.xml包及其子包;
org.w3c.dom包及其子包;
org.xml.sax包及其子包。

DOM:Document Object Model,W3C推荐使用。
特点:一次性将整份XML导入内存,转换成DOM树,因此转换速度慢;但因为常驻内存,所以重复访问效率高,并且可修改节点内容。
SAX:Simple API for XML,费W3C推荐标准,但确实XML行业规范。
特点:顺序解析,无需一次性导入,转换速度快;不保持以访问过的数据,所以重复访问效率低(需要重新解析XML),且无法修改节点内容。

解析器:目前最流行的是Apache组织的Xerces项目。 网址:http://xerces.apache.org/

xerces提供的包
xml-apis.jar:该包就是DOM和SAX标准的核心包,该包里几乎全是接口。
xercesImpl.jar:核心类库。

下面简单介绍下java.xml.parsers包
DocumentBuilderFactory:获取DOM解析器的工厂;
DocumentBuilder:用于从XML文档中获取DOM文档实例;
SAXParserFactory:获取SAX解析器的工厂;
SAXParser:包装一个SAX解析器。

DocumentBuilder、SAXParser都是抽象类,其实现由XML解析器完成。

jdk1.4默认包括一种解析器Crimson,jdk1.5 左右XML解析器默认是Apache组织的Xerces。 可以通过JVM或者工厂方法参数的配置来改变jaxp的解析器。

简单代码示例DocumentBuilderFactory的用法:

public class XmlParserTest {
	public static void main(String[] args) throws Exception {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document doc = builder
				.parse(Thread.currentThread().getContextClassLoader().getResourceAsStream("char02/test.xml"));
		Element root = doc.getDocumentElement();
		NodeList books = root.getChildNodes();
		if (books != null) {
			for (int i = 0; i < books.getLength(); i++) {
				Node book = books.item(i);
				if(book.getNodeType()==Node.ELEMENT_NODE){
					String email=book.getAttributes().getNamedItem("id").getNodeValue();
					System.out.println("email:"+email);
					for (Node node = book.getFirstChild(); node != null; node = node.getNextSibling()) {
						if (node.getNodeType() == Node.ELEMENT_NODE) {
							if(node.getNodeName().equals("name")){
								System.out.println(node.getTextContent());
								System.out.println("name:"+node.getFirstChild().getNodeValue());
							}
							if(node.getNodeName().equals("price")){
								System.out.println("price:"+node.getFirstChild().getNodeValue());
							}
						}
					}
				}
			}
		}
	}
}
<?xml version="1.0" encoding="UTF-8" ?>
<books>
	<book id="01">
		<name>testname</name>
		<price>10.00</price>
	</book>
	<book id="02">
		<name>testname02</name>
		<price>10.02</price>
	</book>
</books> 

继续源码分析:
获取到Document要去注册 BeanDefinitionDocument

这里又 交给我了DocumentReader去注册:
BeanDefinitionDocumentReader 是一个接口,只有一个默认的实现DefaultBeanDefinitionDocumentReader
注册代码为:

处理Elemet:

这里的解析之前的操作和解析之后的操作 都是空的 可以自定义操作:
解析 操作:

红色标记表示对bean的操作:

  • spring 中有两大bean声明:
  1. 一类是默认的:
  2. 另一类是:
    tx:annotation-driven/

注册代码:

2017/5/13 查看源码的时候发现

这里的 beanDefinitionDocumentReader 既然是 通过反射生成的,查看代码知道 beanDefinitionDocumentReader 是可以配置的 但是必须实现beanDefinitionDocumentReader 接口。

posted @ 2017-05-10 22:51  风中小蘑菇  阅读(170)  评论(0编辑  收藏  举报