热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

spring源码的xml解析过程1(默认标签和自定义标签解析)

文章目录源码分析目录spring源码的xml解析过程xml解析总结源码分析目录spring源码的xml解析过程annotation的支持spring中的实例化以及ioc的过程ha

文章目录

      • 源码分析目录
      • spring源码的xml解析过程
        • xml解析
        • 总结


源码分析目录


  1. spring源码的xml解析过程
  2. annotation的支持
  3. spring中的实例化以及ioc的过程
  4. handlermapping和handlerAdapter请求响应过程
  5. 视图解析
  6. aop以及事物管理

spring源码的xml解析过程

从 DispatcherServlet 类开始看。
org.springframework.web.servlet.HttpServletBean#init

initServletBean()

org.springframework.web.servlet.FrameworkServlet#initServletBean

this.webApplicationContext = initWebApplicationContext();

org.springframework.web.servlet.FrameworkServlet#initWebApplicationContext

configureAndRefreshWebApplicationContext(cwac);

org.springframework.web.servlet.FrameworkServlet#configureAndRefreshWebApplicationContext

wac.refresh();

org.springframework.context.support.AbstractApplicationContext#refresh

//xml解析
//注解的解析
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory

refreshBeanFactory();

org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory

//实现类有xml解析和注解的解析
loadBeanDefinitions(beanFactory);

xml解析

org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.support.DefaultListableBeanFactory)

loadBeanDefinitions(beanDefinitionReader);

org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.xml.XmlBeanDefinitionReader)

//xml文件变为 Resource 对象后,解析
reader.loadBeanDefinitions(configResources);

org.springframework.beans.factory.support.AbstractBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.Resource…)

for (Resource resource : resources) {// xml 解析counter += loadBeanDefinitions(resource);
}

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.Resource)

return loadBeanDefinitions(new EncodedResource(resource));

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.support.EncodedResource)

try {//文件流InputStream inputStream = encodedResource.getResource().getInputStream();try {// InputSource 是 dk 中的 xml 解析对象InputSource inputSource = new InputSource(inputStream);if (encodedResource.getEncoding() != null) {inputSource.setEncoding(encodedResource.getEncoding());}// xml 解析return doLoadBeanDefinitions(inputSource, encodedResource.getResource());}finally {inputStream.close();}}

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#doLoadBeanDefinitions

try {// xml 解析为 Document 对象Document doc = doLoadDocument(inputSource, resource);return registerBeanDefinitions(doc, resource);}

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {//xml 文档解析器BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();int countBefore = getRegistry().getBeanDefinitionCount();documentReader.registerBeanDefinitions(doc, createReaderContext(resource));return getRegistry().getBeanDefinitionCount() - countBefore;}

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#registerBeanDefinitions

xml 文件中的根节点&#xff0c;即 <beans>
Element root &#61; doc.getDocumentElement();
doRegisterBeanDefinitions(root);

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions

parseBeanDefinitions(root, this.delegate);

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitions

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {if (delegate.isDefaultNamespace(root)) {NodeList nl &#61; root.getChildNodes();for (int i &#61; 0; i < nl.getLength(); i&#43;&#43;) {Node node &#61; nl.item(i);if (node instanceof Element) {Element ele &#61; (Element) node;if (delegate.isDefaultNamespace(ele)) {//解析 xml 中默认的元素&#xff0c;默认标签&#xff1a;import 、alias、bean、beansparseDefaultElement(ele, delegate);}else {// 解析 xml 中 自定义的元素delegate.parseCustomElement(ele);}}}}else {delegate.parseCustomElement(root);}}

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseDefaultElement

// bean 标签解析
processBeanDefinition(ele, delegate);

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#processBeanDefinition

BeanDefinitionHolder bdHolder &#61; delegate.parseBeanDefinitionElement(ele);

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)

String beanName &#61; id;
AbstractBeanDefinition beanDefinition &#61;
parseBeanDefinitionElement(ele, beanName, containingBean);

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionElement(org.w3c.dom.Element, java.lang.String, org.springframework.beans.factory.config.BeanDefinition)

AbstractBeanDefinition bd &#61;
createBeanDefinition(className, parent);

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#createBeanDefinition

return BeanDefinitionReaderUtils.createBeanDefinition(parentName, className,this.readerContext.getBeanClassLoader());

org.springframework.beans.factory.support.BeanDefinitionReaderUtils#createBeanDefinition

GenericBeanDefinition bd &#61; new GenericBeanDefinition();bd.setParentName(parentName);if (className !&#61; null) {if (classLoader !&#61; null) {// 获取 class 元素配置的类bd.setBeanClass(ClassUtils.forName(className, classLoader));}else {bd.setBeanClassName(className);}}return bd;

返回到
org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionElement(org.w3c.dom.Element, java.lang.String, org.springframework.beans.factory.config.BeanDefinition)

//得到 BeanDefinition 对象
AbstractBeanDefinition bd &#61; createBeanDefinition(className, parent);
//bean 标签上的元素解析&#xff0c;并封装到 db 中&#xff0c;即 BeanDefinition 对象中
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);

BeanDefinition 对象

  1. 会把 xml 中的标签元素&#xff0c;比如 bean,componentScan,annotation-config 标签中的元素信息封装成 BeanDefinition 对象&#xff0c;
  2. 会把 annotation &#xff0c;比如 &#64;Service、&#64;Controller、&#64;Component、&#64;Resource 等注解的类&#xff0c;封装成 BeanDefinition 对象

返回到
org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)

AbstractBeanDefinition beanDefinition &#61; parseBeanDefinitionElement(ele, beanName, containingBean);

返回到
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#processBeanDefinition
返回到
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitions

// 自定义标签解析
delegate.parseCustomElement(ele);

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseCustomElement(org.w3c.dom.Element)

return parseCustomElement(ele, null);

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseCustomElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)

public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {//元素的对应的 NamespaceURIString namespaceUri &#61; getNamespaceURI(ele);//根据 NamespaceURI 拿到到应的处理类&#xff0c;即 NamespaceHandler NamespaceHandler handler &#61; this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);if (handler &#61;&#61; null) {error("Unable to locate Spring NamespaceHandler for XML schema namespace [" &#43; namespaceUri &#43; "]", ele);return null;}return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));}

NamespaceURI 就是 beans 标签的 xmlns 、 xmlns:context、xmlns:aop、xmlns:tx 后面uri

org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#resolve

Map<String, Object> handlerMappings &#61; getHandlerMappings();

org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#getHandlerMappings

//加载所有的配置文件
Properties mappings &#61;
PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);Map<String, Object> handlerMappings &#61; new ConcurrentHashMap<String, Object>(mappings.size());
CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
//返回这个 map,
this.handlerMappings &#61; handlerMappings;

查看 4.3.12.RELEASE\spring-context-4.3.12.RELEASE.jar!\META-INF\spring.handlers
注册 spring context 自定义标签解析器 org.springframework.context.config.ContextNamespaceHandler
查看 spring-webmvc-4.3.12.RELEASE.jar!\META-INF\spring.handlers
注册 spring mvc 自定义的标签解析器 org.springframework.web.servlet.config.MvcNamespaceHandler
返回到
org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#resolve

Map<String, Object> handlerMappings &#61; getHandlerMappings();
Object handlerOrClassName &#61; handlerMappings.get(namespaceUri);
// 例如&#xff1a;handlerOrClassName 就是指 ContextNamespaceHandler
String className &#61; (String) handlerOrClassName;
// new 出 ContextNamespaceHandler 的实例
NamespaceHandler namespaceHandler &#61; (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
// 调用注册方法&#xff0c;注册自定义标签的解析器
namespaceHandler.init();
//返回
return namespaceHandler;

返回到
org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseCustomElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)

String namespaceUri &#61; getNamespaceURI(ele);
NamespaceHandler handler &#61;
this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));

org.springframework.beans.factory.xml.NamespaceHandlerSupport#parse

// 根据标签找到到应的解析器&#xff0c;再调用 parse 方法解析标签&#xff0c;即 element
return findParserForElement(element, parserContext).parse(element, parserContext);

org.springframework.beans.factory.xml.NamespaceHandlerSupport#findParserForElement

//得到标签对就的处理类
String localName &#61; parserContext.getDelegate().getLocalName(element);
BeanDefinitionParser parser &#61; this.parsers.get(localName);
return parser;

总结


  1. spring 分析入口
  2. xml 默认元素解析过程
  3. xml 自定义标签配置和解析

推荐阅读
author-avatar
雷神白中凌
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有