上面一篇文件讲了BeanDefinition的原理。这一篇讲spring解析xml的时候一些小特点。主要是验证,然后不同的xml名称空间会有不同的类来解析xml。解析xml,spring没有用到第三方库,而是直接使用java的api。这里是和spring解析xml类似的代码。我们从这里开始。
@Test public void testSpringReaderXml() throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); //设置解析xml的时候验证xml的格式 factory.setValidating(true); factory.setAttribute(SCHEMA_LANGUAGE_ATTRIBUTE, XSD_SCHEMA_LANGUAGE); factory.setExpandEntityReferences(true); DocumentBuilder docBuilder = factory.newDocumentBuilder(); //设置解析验证实例 docBuilder.setEntityResolver(new EntityResolver() { @Override public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { //验证xml时要用到的xsd文件,对应schemaLocation的value InputSource source = new InputSource(TestXSD.class.getResourceAsStream("D:\\workspaceStudy\\spring_study\\src\\spring-beans-3.0.xsd")); source.setPublicId(publicId); //验证xml对应的schemaLocation的key source.setSystemId("http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"); return source; } }); //设置解析错误时回调方法 docBuilder.setErrorHandler(new ErrorHandler() { @Override public void warning(SAXParseException exception) throws SAXException { exception.printStackTrace(); throw exception; } @Override public void error(SAXParseException exception) throws SAXException { // TODO Auto-generated method stub exception.printStackTrace(); throw exception; } @Override public void fatalError(SAXParseException exception) throws SAXException { // TODO Auto-generated method stub exception.printStackTrace(); throw exception; } }); Document document = docBuilder .parse("D:\\workspaceStudy\\spring_study\\src\\beanFactory2.xml"); Element root = document.getDocumentElement(); String nodeName = root.getNodeName(); System.out.println("nodeName:" + nodeName + " ;namespace:" + root.getNamespaceURI()); 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; System.out.println(ele.getLocalName() + ":" + ele.getAttribute("id")); } } System.out.println("validate true"); }
spring解析是直接用DocumentBuilder这个类生成Document,然后通过Document得到不同的Element,并且不同的Element,为不同的方法解析。解析xml时验证的实例就会用到PluggableSchemaResolver类。
public class PluggableSchemaResolver implements EntityResolver { /** * The location of the file that defines schema mappings. * Can be present in multiple JAR files. */ public static final String DEFAULT_SCHEMA_MAPPINGS_LOCATION = "META-INF/spring.schemas"; private static final Log logger = LogFactory.getLog(PluggableSchemaResolver.class); private final ClassLoader classLoader; private final String schemaMappingsLocation; /** Stores the mapping of schema URL -> local schema path */ private volatile Map<String, String> schemaMappings; 。。。。。 public InputSource resolveEntity(String publicId, String systemId) throws IOException { if (logger.isTraceEnabled()) { logger.trace("Trying to resolve XML entity with public id [" + publicId + "] and system id [" + systemId + "]"); } if (systemId != null) { String resourceLocation = getSchemaMappings().get(systemId); if (resourceLocation != null) { Resource resource = new ClassPathResource(resourceLocation, this.classLoader); try { InputSource source = new InputSource(resource.getInputStream()); source.setPublicId(publicId); source.setSystemId(systemId); if (logger.isDebugEnabled()) { logger.debug("Found XML schema [" + systemId + "] in classpath: " + resourceLocation); } return source; } catch (FileNotFoundException ex) { if (logger.isDebugEnabled()) { logger.debug("Couldn't find XML schema [" + systemId + "]: " + resource, ex); } } } } return null; } }
上面的schemaMappings就是存放url对应的xsd地址。这里是读classpath路径下所有的META-INF/spring.schemas文件。读的方法就类似下面:
@Test public void testMeta() throws IOException { ClassLoader cld = Thread.currentThread().getContextClassLoader(); Enumeration enumURL = cld.getResources("META-INF/spring.schemas"); int count = 0; while (enumURL.hasMoreElements()) { URL url = (URL) enumURL.nextElement(); count++; System.out.println(url.getFile()); InputStream is = url.openConnection().getInputStream(); int i = is.read(); while (i != -1) { System.out.print((char) i); i = is.read(); } System.out.println(); is.close(); } System.out.println(count); }
相关推荐
spring4.0源码,需要的可以下载,还是很完整的.
spring4.0.x源码
Spring 4.0.x版本的源代码。
spirng4的jar以及相关的jar依赖
利用maven构建的spring4.0框架的demo
spring4.0完整jar包 包含spring4.0 所有的jar包文件 打包下载
spring4.0框架所需的jar包,没有包含maven,没有其他框架用的jar包,仅仅是spring框架,每一个都是自己下载的,搭建成功。
Spring4.0+Hibernate4.0+Struts2.3整合案例:实现增删改查。 ===================== application.xml: <?xml version="1.0" encoding="UTF-8"?> xmlns="http://www.springframework.org/schema/beans" xmlns:xsi=...
Spring4.0-API CHM格式,很难得的,希望能帮到大家!
spring-framework也就是Spring4.0官方jar包,Spring框架,由Rod Johnson开发,是一个非常强大的反转控制(IOC)框架,以帮助分离项目组件之间的依赖关系
spring4.0详细教程,简单明了,一看即懂 ,适合初学者
Spring框架4.0这个版本支持了众多Java 8的新特性,新增了对WebSocket、STOMP等技术的支持,并增强了测试、Web开发的便利性,另外,在这个版本中还删除了废弃的方法和类。
spring4.0+spring MVC4.0+hibernate4.3框架整合测试案例,支持事务,全注解,配置清晰,基础BaseDao接口实现都已写好,MVC分层,含所有需要的jar包,数据库文件。
Spring4.0+SpringMVC4.0+Mybatis3.2框架整合例子(SSM) 自动生成代码 简单试用
Spring4.0源代码,GitHub 2014.1月份最新版
Spring4.0的jar包,官方源码,javadoc
这是一篇总结Spring5源码深度解析的文档,By 某Tom老师,很经典,讲解深入浅出!