ibatis配置文件解析之总体流程

本文深入探讨了iBatis配置文件解析的整体流程,从初始化配置对象到执行解析方法,通过创建NodeletParser和注册Nodelet实现类,实现了对配置文件的高效解析。解析过程采用递归方式,通过生成xpath和调用相应的Nodelet方法,完成配置文件的逐层解析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:http://blog.youkuaiyun.com/prince2270/article/details/5998160

 配置文件解析是使用iBatis的第一步。那么,ibatis是如何实现其配置文件解析呢?本文将在较高的抽象层次上讲述ibatis配置文件解析的总体流程。

     一切都从new SqlMapConfigParser().parse(reader);这条语句开始的。这条语句包含了ibatis配置文件解析的全部内容。这条语句包括两部分内容:创建sqlMapConfigParser对象和执行器parse方法。下面就分别来讲述这两部分内容究竟做了些什么工作。

     首先看一下SqlMapConfigParser对象创建时执行了哪些操作。

[java]  view plain copy
  1. protected final NodeletParser parser = new NodeletParser();  
  2.   
  3. private XmlParserState state = new XmlParserState();  
  4.   
  5. public SqlMapConfigParser() {  
  6.     //验证  
  7.     parser.setValidation(true);  
  8.     //定位DTD文件  
  9.     parser.setEntityResolver(new SqlMapClasspathEntityResolver());  
  10.   
  11.     //Nodelet注册  
  12.     addSqlMapConfigNodelets();  
  13.     addGlobalPropNodelets();  
  14.     addSettingsNodelets();  
  15.     addTypeAliasNodelets();  
  16.     addTypeHandlerNodelets();  
  17.     addTransactionManagerNodelets();  
  18.     addSqlMapNodelets();  
  19.     addResultObjectFactoryNodelets();  
  20.   }  

     第一个操作:创建NodeletParser对象,这个类定义了配置文件解析的通用模板方法,即如何遍历配置文件并进行处理。

     第二个操作:创建XmlParserState对象,这个类的用途暂时可以先不关注。

     第三个操作:执行构造函数。在构造函数中进行了配置文件的验证,以及Nodelet的注册。这里就会有两个疑问了,Nodelet是干什么的,被注册到哪里了。

     先说明一下Nodelet的作用,Nodelet是ibatis节点解析的抽象接口,定义如下:

[java]  view plain copy
  1. public interface Nodelet {    
  2.     void process (Node node) throws Exception;  
  3. }  

    一个Nodelet接口的实现类能够处以一类xml节点。然后就是Nodelet实现类的注册了,在SqlMapConfigParser类的构造函数中,将SqlMapConfig配置文件相关的节点的解析类(Nodelet的实现类)注册到letMap中。这是letMap是一个Map,是NodeletParser的一个属性,其key为xpath,value为Nodelet实现类的实例。这个注册后letMap会在xml文件解析中被使用。

    以上这些操作都是在为配置文件的解析做准备,接下来就要看ibatis是如何解析配置文件了。先看SqlMapConfigParser的parse方法,它调用了NodeletParser的parse方法,下面看一下具体的实现代码:

[c-sharp]  view plain copy
  1. //解析根节点    
  2. public void parse(Node node) {  
  3.     Path path = new Path();  
  4.     processNodelet(node, "/");  
  5.     process(node, path);  
  6. }  
  7. //解析单个节点参数node为被解析的节点,参数pathString是该节点对应的xpath信息  
  8.   private void processNodelet(Node node, String pathString) {  
  9.     //从letMap中根据xpath取得之前注册的Nodelet实例  
  10.     Nodelet nodelet = (Nodelet) letMap.get(pathString);  
  11.     if (nodelet != null) {  
  12.       try {  
  13.         //执行真正的节点解析  
  14.         nodelet.process(node);  
  15.       } catch (Exception e) {  
  16.         throw new RuntimeException("Error parsing XPath '" + pathString + "'.  Cause: " + e, e);  
  17.       }  
  18.     }  
  19.   }  
  20.   
  21. //处理xml配置文件,最开始是从根路径开始的  
  22. //参数path是用来生成xpath的  
  23. private void process(Node node, Path path) {  
  24.     if (node instanceof Element) {  
  25.       // Element  
  26.       String elementName = node.getNodeName();  
  27.       path.add(elementName);  
  28.       processNodelet(node, path.toString());  
  29.       processNodelet(node, new StringBuffer("//").append(elementName).toString());  
  30.   
  31.       // Attribute  
  32.       NamedNodeMap attributes = node.getAttributes();  
  33.       int n = attributes.getLength();  
  34.       for (int i = 0; i < n; i++) {  
  35.         Node att = attributes.item(i);  
  36.         String attrName = att.getNodeName();  
  37.         path.add("@" + attrName);  
  38.         processNodelet(att, path.toString());  
  39.         processNodelet(node, new StringBuffer("//@").append(attrName).toString());  
  40.         path.remove();  
  41.       }  
  42.   
  43.       // Children  
  44.       NodeList children = node.getChildNodes();  
  45.       for (int i = 0; i < children.getLength(); i++) {  
  46.         //递归解析子节点  
  47.         process(children.item(i), path);  
  48.       }  
  49.       path.add("end()");  
  50.       processNodelet(node, path.toString());  
  51.       path.remove();  
  52.       path.remove();  
  53.     } else if (node instanceof Text) {  
  54.       // Text  
  55.       path.add("text()");  
  56.       processNodelet(node, path.toString());  
  57.       processNodelet(node, "//text()");  
  58.       path.remove();  
  59.     }  
  60.   }  

     以上代码即为ibatis解析配置文件的主要流程了,至于单个节点如何解析和解析后数据存储在什么地方在这里暂不做详细讨论。下面来总结一下ibatis解析配置文件的大体思路:

     1. 定义了Nodelet接口,可以处理各种类型的xml节点。

     2. 准备工作,注册Nodelet实例,将xpath和Nodelet实例关联起来。

     3. 解析,在NodeletParser中,递归解析处理配置文件,根据Node信息生成xpath,根据xpath取得Nodelet实例,并执行其process方法,从而完成了配置文件的解析工作。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值