iBatis2 Source Analysis (1) - xml parsing module

Like with most of the ORM framework, iBatis2 is described with Xml ORM mapping information (before the appearance of the annotations), then the XML parsing configuration information is then how? Oh, most people see here might say: This Yousha difficult, parsing xml using DOM or SAX is very easy! IBatis xml parsing does nothing less than the methods that either, but carefully read the iBatis source code parsing XML, I found that iBatis xml parsing code which we can learn ... ...

iBatis the most important interface is SqlMapClient, first look at how the procedure is the same kind had been SqlMapClient object configuration files:

  static { 
                try { 
                        String resource = "com/ppsoft/ibatis/test/config/SqlMapConfig.xml"; 
                        Reader reader = Resources.getResourceAsReader (resource); 
                        sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader); 
                } catch (Exception e) { 
                        e.printStackTrace(); 
                        throw new RuntimeException ("Error initializing MyAppSqlConfig class. Cause:"+e); 
                } 
        }


Class SqlMapClientBuilder provides several static methods for reading configuration files and create SqlMapClient iBatis object, this chapter is to analyze how to read iBatis configuration file, so also look at some of parsing xml files that look buildSqlMapClient method has done both:

  public static SqlMapClient buildSqlMapClient(Reader reader) {
        return new SqlMapConfigParser().parse(reader);
  }


First create a SqlMapConfigParser, call the newly created parser object SqlMapConfigParser method, xml parsing, and creating

SqlMapClient entrusted to the SqlMapConfigParser object. So then look at the parse methods SqlMapConfigParser done some

Sha:

  public SqlMapClient parse(Reader reader) {
    try {
      usingStreams = false;
      parser.parse(reader);
      return state.getConfig().getClient();
    } catch (Exception e) {
      throw new RuntimeException("Error occurred.  Cause: " + e, e);
    }
  }

Oh, see here you will find, in fact, the parse method did not SqlMapConfigParser Anythin only analytical work will be entrusted to SqlMapConfigParser a parser property to see SqlMapConfigParser the parser property is valid and things:

  protected final NodeletParser parser = new NodeletParser();
  //state Used to store all the information analytical  
  private XmlParserState state = new XmlParserState();


The original property is a NodeletParser parser object, xml is parsed by the NodeletParser this class, the class focused on the following analysis. Then let us look at NodeletParser parse this class is how to parse xml's:

  public void parse(Reader reader) throws NodeletException {
    try {
      Document doc = createDocument(reader);
      parse(doc.getLastChild());
    } catch (Exception e) {
      throw new NodeletException("Error parsing XML.  Cause: " + e, e);
    }
  }

First create a document object (called JAXP created and tested under the DTD file is correct xml format) and then call another overloaded NodeletParser in the parse method:

  public void parse(Node node) {
    Path path = new Path();
    processNodelet(node, "/");
    process(node, path);
  }

First create a Path object (Path is defined NodeletParser an internal class), then call processNodelet method, and finally calls the process (node, path); first look processNodelet method doing wrong?

private void processNodelet(Node node, String pathString) {
    Nodelet nodelet = (Nodelet) letMap.get(pathString);
    if (nodelet != null) {
      try {
        nodelet.process(node);
      } catch (Exception e) {
        throw new RuntimeException("Error parsing XPath '" + pathString + "'.  Cause: " + e, e);
      }
    }
  }

Parameter pathString fact is xpath string, you can see from this code have letMap NodeletParser property is a Map, to xpath as the key, Nodelet object to value. The code logic is: According to the introduction of the xpath search letMap have no corresponding Nodelet object, if the object to call the corresponding process Nodelet method parameters to deal with the Node. Well, this Nodelet in the end is what is it? Look at the code will know then:

public interface Nodelet {
    void process (Node node) throws Exception;
}

Interfaces to the original just would abstract out the processing nodes, the design very clear: the node approach into Nodelet abstract interfaces, sqlMap stored in the processing of Nodelet each Node object (we can call it Node processor), key for the Node of the xpath, if we specify a good processor for each Node object, then only need to traverse all the nodes, and to find the corresponding Nodelet sqlMap object call its process method to complete the analytical processing of the xml.

Here we analyze the next process (node, path) method done things. See the code before this method in this class come to see why Path:

  private static class Path {
    private List nodeList = new ArrayList();
    public Path() {
    }
    public Path(String xpath) {
      StringTokenizer parser = new StringTokenizer(path, "/", false);
      while (parser.hasMoreTokens()) {
        nodeList.add(parser.nextToken());
      }
    }
    public void add(String node) {
      nodeList.add(node);
    }

    // Remove xpath path to the last node in the  
    public void remove() {
      nodeList.remove(nodeList.size() - 1);
    }

    public String toString() {
      StringBuffer buffer = new StringBuffer("/");
      for (int i = 0; i < nodeList.size(); i++) {
        buffer.append(nodeList.get(i));
        if (i < nodeList.size() - 1) {
          buffer.append("/");
        }
      }
      return buffer.toString();
    }
  }

Look at source, we know that this class is really just used to describe the xpath of, xpath all the nodes are sequentially placed in a List of, and replication of the toString method will be converted to Xpath string List, other, Path class provides two important ways add and remove, add to add a child node, if the original xpath is / root, called add ("element1"), after, path becomes / root/element1; remove method is used to remove the path in the last node, and add the opposite.

Further analysis of the next process (node, path) code, the code is as follows:

  private void process(Node node, Path path) {
    if (node instanceof Element) {
      // Element
      String elementName = node.getNodeName();
      path.add(elementName);
      processNodelet(node, path.toString());
      processNodelet(node, new StringBuffer("//").append(elementName).toString());
      //  All of the processing node  Attribute
      NamedNodeMap attributes = node.getAttributes();
      int n = attributes.getLength();
      for (int i = 0; i < n; i++) {
        Node att = attributes.item(i);
        String attrName = att.getNodeName();
        path.add("@" + attrName);
        processNodelet(att, path.toString());
        processNodelet(node, new StringBuffer("//@").append(attrName).toString());
        path.remove();
      }

      //  Recursive traversal of all node  Children
      NodeList children = node.getChildNodes();
      for (int i = 0; i < children.getLength(); i++) {
        process(children.item(i), path);
      }

      //node As well as its child nodes at the end of the call  node By  end() Processor  
      path.add("end()");
      processNodelet(node, path.toString());
      path.remove();
      path.remove();
    } else if (node instanceof Text) {
      //  If it is  Text
      path.add("text()");
      processNodelet(node, path.toString());
      processNodelet(node, "//text()");
      path.remove();
    }
  }

Code, plus some brief notes, a closer look will understand, process (Node node, Path path) method of recursive traversal of the node, node attributes and node all the all the child nodes, and call processNodelet, which also confirms previous speculation the correctness (see the previous method of analysis of the processNodelet).

Based on the above analysis, we know that each Node xml processing of information (previously mentioned information processing abstraction for the interface Node Nodelet) are to Node of the xpath for the key stored in NodeletParser class letMap, then how we Registration for each Node Processor (Nodelet object) do?

Let us look back SqlMapConfigParser code, first look at SqlMapConfigParser the constructor:

  public SqlMapConfigParser() {
    parser.setValidation(true);
    // Set the DTD files  classpath Map  
    parser.setEntityResolver(new SqlMapClasspathEntityResolver());
    // Registered Node processor  
    addSqlMapConfigNodelets();
    addGlobalPropNodelets();
    addSettingsNodelets();
    addTypeAliasNodelets();
    addTypeHandlerNodelets();
    addTransactionManagerNodelets();
    addSqlMapNodelets();
    addResultObjectFactoryNodelets();
  }

Can see the constructor above one half of the code is addXXX form, this is the xml document to the Node Registration processor (Nodelet object)

We had a quick look at a addXXX methods to see how the registered Node inside the processor, to see SqlMapConfigParser of addTypeAliasNodelets () method of it:

  /**
   *  Registered typeAlias processor  
   */
  private void addTypeAliasNodelets() {
    parser.addNodelet("/sqlMapConfig/typeAlias", new Nodelet() {
      public void process(Node node) throws Exception {
        Properties prop = NodeletUtils.parseAttributes(node, state.getGlobalProps());
        String alias = prop.getProperty("alias");
        String type = prop.getProperty("type");
        state.getConfig().getTypeHandlerFactory().putTypeAlias(alias, type);
      }
    });
  }

Here the parser calls the class SqlMapConfigParser attributes (here's parser in front of said property is an instance of NodeletParser) of addNodelet method, originally called this method the node to the xml registration processor. NodeletParser method addNodelet the first parameter is a xpath, xml is used to represent the Node; the second parameter is the node processor (Nodelet object), designated to handle xpath xml nodes, where Nodelet is to use anonymous inner classes implementation; we look NodeletParser the addNodelet method code:

  public void addNodelet(String xpath, Nodelet nodelet) {
    letMap.put(xpath, nodelet);
  }

Nodelet object is letMap the map!

Look here / sqlMapConfig / typeAlias how the deal:

  1. First of all, the parseAttribute calculated by NodeletUtils out / sqlMapConfig / typeAlias all the attribute values of nodes to return Properties object, attribute named key, attribute value value, where property values will with $ () This expression value out.
  2. Attribute values from the returned Properties object access / sqlMapConfig / typeAlias node alias and type attributes.
  3. The extracted information into TypeHanderFactory typeAlias alias mapping table.

Other Node in the same way the processor register NodeletParser object. Object to NodeletParser registered after all the required Nodelet processor, called NodeletParser the parser method can be xml parsing out the specific treatment of each node is how is our own designated, NodeletParser only defines how to traverse all the nodes in xml method.

NodeletParser application of the Template Method Pattern in fact the idea, in NodeletParser defines how to traverse all the nodes in xml the method, but does not define how the node is, but by using the specified Node's Nodelet processor, when the node when traversing to call the corresponding Nodelet the process methods to achieve code reuse, so that has nothing to do with specific xml file.

there is a category under com.ibatis.sqlmap.engine.builder.xml package SqlMapParser, used SqlMap file parsing, parsing the same manner and SqlMapConfigParser is through NodeletParser, NodeletParser object to the registration Nodelet processor files on SqlMap analysis.

The following class diagram is analytic SqlMapConfig iBatis files and files of several of the most SqlMap core of the relationship between several classes:

iBatis2 Source Analysis (1) - xml parsing module

The basic iBatis xml parsing module has been very clear, carefully analyzing the code, I first felt good to see other people's code, designed the fun, plan to continue reading later iBatis source code, of course, I will write down the flu Wu ~
  • del.icio.us
  • StumbleUpon
  • Digg
  • TwitThis
  • Mixx
  • Technorati
  • Facebook
  • NewsVine
  • Reddit
  • Google
  • LinkedIn
  • YahooMyWeb

Related Posts of iBatis2 Source Analysis (1) - xml parsing module

  • The merits of the field-driven development

    All along, J2ee development process (in Struts + Hibernate + Spring as an example) are as follows: 1. Design Database 2. Generate database 3. From the project to establish database connection 4. Put the database reverse engineering to generate POJO 5 ...

  • Hundred software developers interview question

    Hundred software developers interview question Think employed to engage in software development of smart people is not easy. The event of accidentally, it will get a pile of low-energy large baboons. I met last year on this matter. You certainly do not wa

  • Struts2 Spring Hibernate integration of easy

    1. Add Spring 2.0 in Libraries Choose the following four jar, and configure the / WEB-INF/lib under Spring2.0 AOP Libraries Spring2.0 Core Libraries Spring2.0 Persistence Core Libraries Spring2.0 WEb Libraries At the same time, the applicationContext ...

  • Struts2 Spring Hibernate's easy to integrate

    1. Add Spring 2.0 in Libraries Choose the following four jar, and configure the / WEB-INF/lib under Spring2.0 AOP Libraries Spring2.0 Core Libraries Spring2.0 Persistence Core Libraries Spring2.0 WEb Libraries At the same time, the applicationContext ...

  • Hibernate Inteceptor

    The end of the project stage, the client suddenly put forward a very troublesome but normal demand, the system records all changes must be carried out. Formats such as: 2004.1.1 12:30 Ikuya wind orders Sales Order Date 2004.1.2-> 2004.1.3 The firs ...

  • jboss ejb3 Message Driven Bean

    Super Medium ejb hate. . . . . . . . . . . . . . . . . . . ================================================ To configure a Message Driven Bean in a different application server parameters are not the same. Currently only passed the test jboss. Message Dri

  • java read file

    java read documents in two ways: java.io and java.lang.ClassLoader When using the java.io, when java.lang.ClassLoader use it? (Note: If prior to read xml file java read file clearly aware of these two methods have been like! Can take much less to understa

  • Hibernate configuration parameters hibernate.hbm2ddl.auto

    Hibernate in the configuration file: <properties> <property name="hibernate.hbm2ddl.auto" value="create" /> </ properties> Parameter Description: validate load hibernate, the authentication to create a database t ...

  • WebQQ, ExtJs + Servlet + Hibernate + Spring implementation

    Code for the development of boredom when using ExtJs + Servlet + hibernate (Ant + xdoclet generate HBM files) + spring implementation, Pure whim, but implementation has been more than chat, group chat, what's not achieve, nor how to consider the perfo

  • Java technology: Eclipse explain the use of techniques

    Editor settings: Window -> Preferences -> Java-> Editor appearance: Display line number, emphasizing symmetry shown in square brackets, to emphasize that the existing line to show Print Margins its check, Tab width set 4, print made from the fiel

blog comments powered by Disqus
Recent
Recent Entries
Tag Cloud
Random Entries