一、XML基础
DTD、XML阐述、XML的两种文档类型约束和DTD的使用-CSDN博客
二、new File()、getResource()、getResourceAsStream()
Java中Class类和 ClassLoader 类 的 getResource()和 getResourceAsStream()方法的使用_getclassloader().getresourceasstream-CSDN博客
三、spring的XmlBeanDefinitionReader
1、把文档读取委托给DocumentLoader执行,DefaultDocumentLoader是其实现类。
2、doLoadBeanDefinitions()方法:1)读取到Doc里面;2)解析Doc注册为BeanDefinition。
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)throws BeanDefinitionStoreException {try {Document doc = doLoadDocument(inputSource, resource);int count = registerBeanDefinitions(doc, resource);if (logger.isDebugEnabled()) {logger.debug("Loaded " + count + " bean definitions from " + resource);}return count;}catch (BeanDefinitionStoreException ex) {throw ex;}catch (SAXParseException ex) {throw new XmlBeanDefinitionStoreException(resource.getDescription(),"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);}catch (SAXException ex) {throw new XmlBeanDefinitionStoreException(resource.getDescription(),"XML document from " + resource + " is invalid", ex);}catch (ParserConfigurationException ex) {throw new BeanDefinitionStoreException(resource.getDescription(),"Parser configuration exception parsing XML from " + resource, ex);}catch (IOException ex) {throw new BeanDefinitionStoreException(resource.getDescription(),"IOException parsing XML document from " + resource, ex);}catch (Throwable ex) {throw new BeanDefinitionStoreException(resource.getDescription(),"Unexpected exception parsing XML document from " + resource, ex);}}
}
3、registerBeanDefinitions方法调用parseBeanDefinitions方法进行bean标签doc元素解析
public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {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)) {
//解析每个bean标签注册为BeanDefinitionparseDefaultElement(ele, delegate);}else {delegate.parseCustomElement(ele);}}}}else {delegate.parseCustomElement(root);}}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)) {// recursedoRegisterBeanDefinitions(ele);}}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));}}}
4、parseBeanDefinitionElement()方法:解析到BeanDefinitionHolder,BeanDefinitionHolder.getBeanDefinition()就得到BeanDefinition。
public class BeanDefinitionParserDelegate {
@Nullablepublic 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 (logger.isTraceEnabled()) {logger.trace("No XML 'id' specified - using '" + beanName +"' as bean name and " + aliases + " as aliases");}}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);// Register an alias for the plain bean class name, if still possible,// if the generator returned the class name plus a suffix.// This is expected for Spring 1.2/2.0 backwards compatibility.String beanClassName = beanDefinition.getBeanClassName();if (beanClassName != null &&beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {aliases.add(beanClassName);}}if (logger.isTraceEnabled()) {logger.trace("Neither XML 'id' nor 'name' specified - " +"using generated bean name [" + beanName + "]");}}catch (Exception ex) {error(ex.getMessage(), ele);return null;}}String[] aliasesArray = StringUtils.toStringArray(aliases);return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);}return null;}
}
四、本地模拟spring读取配置文件
配置文件NewFile.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 视图解析器配置 --><bean id="test" name="testName" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/views/" /><property name="suffix" value=".jsp" /></bean></beans>
package com.hq.other.xml;import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;public class XmlReaderSample {
// private static final String SCHEMA_LANGUAGE_ATTRIBUTE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
// private static final String XSD_SCHEMA_LANGUAGE = "http://www.w3.org/2001/XMLSchema";
// protected final static Log logger = LogFactory.getLog(new XmlReaderSample().getClass());public static void main(String[] args) throws Exception {
// 创建解析工厂DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// factory.setValidating(true);
// factory.setNamespaceAware(true);
// factory.setAttribute(SCHEMA_LANGUAGE_ATTRIBUTE, XSD_SCHEMA_LANGUAGE);
// 由工厂创建文档构建器DocumentBuilder docBuilder = factory.newDocumentBuilder();
// docBuilder.setEntityResolver(new ResourceEntityResolver(new PathMatchingResourcePatternResolver()));
// docBuilder.setErrorHandler(new SimpleSaxErrorHandler(logger));
// 解析项目资源根路径下面的xml文件到documentDocument document=docBuilder.parse(XmlReaderSample.class.getResourceAsStream("/NewFile.xml"));// 获取文档根节点标签<beans>Node root = document.getDocumentElement();
// 打印所有的bean信息printAllBean(root);}private static void printAllBean(Node root) {NodeList children = root.getChildNodes();for(int i=0;i<children.getLength();i++){Node node = children.item(i);if (!(node instanceof Element)) {continue;}Element ele = (Element)node;System.out.println("nodeName:"+ele.getNodeName());System.out.println("class:"+ele.getAttribute("class"));System.out.println("id:"+ele.getAttribute("id"));System.out.println("name:"+ele.getAttribute("name"));}}}
结果:
nodeName:bean
class:org.springframework.web.servlet.view.InternalResourceViewResolver
id:test
name:testName