热门标签 | 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 自定义标签配置和解析

推荐阅读
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • HDFS2.x新特性
    一、集群间数据拷贝scp实现两个远程主机之间的文件复制scp-rhello.txtroothadoop103:useratguiguhello.txt推pushscp-rr ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 本文介绍了在CentOS上安装Python2.7.2的详细步骤,包括下载、解压、编译和安装等操作。同时提供了一些注意事项,以及测试安装是否成功的方法。 ... [详细]
  • Spring学习(4):Spring管理对象之间的关联关系
    本文是关于Spring学习的第四篇文章,讲述了Spring框架中管理对象之间的关联关系。文章介绍了MessageService类和MessagePrinter类的实现,并解释了它们之间的关联关系。通过学习本文,读者可以了解Spring框架中对象之间的关联关系的概念和实现方式。 ... [详细]
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社区 版权所有