Ibatis source code learning 2 _ initialization and Configuration File Parsing

Source: Internet
Author: User
Tags xpath

 

In the ibatis overall design and core process, we mentioned the ibatis framework initialization process. This article will analyze the ibatis framework initialization and configuration file parsing process in depth. The ibatis version used in this article is 2.3.4, which may vary slightly between different versions.

Problem
Before introducing the ibatis initialization process in detail, let's take a look at several questions.

1. What is the goal of ibatis initialization?
As mentioned above, the core objective of ibatis Initialization is to construct the sqlmapclientimpl object, which is mainly the initialization of the proxy object of the important internal attribute delegate. The delegate object is coupled with the user-side operation behavior and execution environment, holding all the data required for the operation.

2. How to parse the ibatis sqlmap configuration file and sqlmap ing file?
You can use common XML file parsing tools, such as sax.

3. How to inject each node value in the configuration file into the sqlmapclientimpl object?
You can set the corresponding handler for different types of nodes. When traversing a node, you can call the handler object processing method to inject the node value into the attributes of the sqlmapclientimpl object.

With the above questions, we began to explore the ibatis initialization process.

Core class diagram
The initialization process mainly involves the following important classes. It is very important to understand the meanings of these classes. The main class diagram is as follows:

1. nodelet
This interface is an abstraction of the node Processing Method in the configuration file. This interface has only one process () method, indicating the processing method for such nodes.

2. nodeletparser
An XML Parser similar to sax. The difference is that sax adopts the same processing method for all nodes, while nodeletparser can customize the corresponding processing method for different nodes. Nodeletparser maintains a letmap internally, which maintains the relationship between the node identification information XPath and the corresponding processing method nodelet.

3. xmlparserstate
It is used to maintain the context information during the parsing of the configuration file. All the data generated during the parsing of the configuration file is stored in xmlparserstate for unified maintenance.
Note: This class is not available in ibatis2.3.0. It uses the internal class variables of baseparser to maintain context information.

4. sqlmapconfigparser
Used to parse the sqlmap configuration file. It combines the nodeletparser object internally to complete the parsing of the sqlmap configuration file. In this object constructor, the node XPath and corresponding nodelet ing relationships in the sqlmap configuration file are added to the nodeletparser attribute. For example, the processing method of the <typealias> node is as follows:

Java code
  1. Private void addtypealiasnodelets (){
  2. Parser. addnodelet ("/sqlmapconfig/typealias ",
    New nodelet (){
  3. Public void process (node)
    Throws exception {
  4. Properties prop = nodeletutils. parseattributes (node, state. getglobalprops ());
    // Parse node Information
  5. String alias = prop. getproperty ("alias ");
  6. String type = prop. getproperty ("type ");
  7. State. getconfig (). gettypehandlerfactory (). puttypealias (alias, type );
    // Write data to xmlparserstate
  8. }
  9. });
  10. }

5. sqlmapparser
Used to parse the sqlmap ing file. It combines the nodeletparser object internally to complete the parsing of the sqlmap ing file. Similar to sqlmapconfigparser, add the node identification information XPath and corresponding nodelet ing relationships in the sqlmap ing file to the nodeletparser attribute in the constructor. For example, the <SQL> node processing method is as follows:

Java code
  1. Private void addsqlnodelets (){
  2. Parser. addnodelet ("/sqlmap/SQL ",
    New nodelet (){
  3. Public void process (node)
    Throws exception {
  4. Properties attributes = nodeletutils. parseattributes (node, state. getglobalprops ());
  5. String id = attributes. getproperty ("ID ");
  6. If (State. isusestatementnamespaces ()){
  7. Id = state. applynamespace (ID );
  8. }
  9. If (State. getsqlincludes (). containskey (ID )){
  10. Throw new sqlmapexception ("Duplicate <SQL>-include '" + ID +
    "'Found .");
  11. } Else {
  12. State. getsqlincludes (). Put (ID, node );
  13. }
  14. }
  15. });
  16. }

6. sqlstatementparser
Used to generate the mappedstatement object corresponding to the SQL statement. It contains only one public method parsegeneralstatement (node, generalstatement statement), which is used to generate the mappedstatement object.

The following uses the common ibatis configuration in the Code as an example to describe the configuration file parsing and initialization process of the ibatis framework.
Common ibatis configurations

Biz-data-source.xml code
  1. <Bean id = "sqlmapclient" class = "org. springframework. Orm. ibatis. sqlmapclientfactorybean">
  2. <Property name = "datasource" ref = "datasource"/>
  3. <Property name = "configlocation" value = "classpath/ sqlmap-ibatis.xml"/>
  4. </Bean>
Configuration File sqlmap-ibatis.xml code
  1. <Sqlmapconfig>
  2. <Sqlmap resource = "sqlmap/cases/casesql. xml"/>
  3. ...
  4. </Sqlmapconfig>
Casing file casesql. XML Code
  1. <Select id = "query-case-by-case-ID" parameterclass = "map" resultmap = "RM-case">
  2. Select ID, gmt_modified, gmt_create, status
  3. From avatar_case
  4. Where id = # caseid #
  5. </SELECT>

Initialization Process
1) sqlmapclientfactorybean Initialization

Sqlmapclientfactorybean initialization method afterpropertiesset (), used to build sqlmapclient object:

Java code
  1. Public void afterpropertiesset ()
    Throws exception {
  2. ...
  3. This. sqlmapclient = buildsqlmapclient (this. configlocations,
    This. mappinglocations, this. sqlmapclientproperties );
    // Initialize the core method to build the sqlmapclient object...
  4. }

The implementation of buildsqlmapclient () is as follows:

Java code
  1. Protected sqlmapclient buildsqlmapclient (
  2. Resource [] configlocations, resource [] mappinglocations, properties Properties)
  3. Throws ioexception {
  4. ...
  5. Sqlmapclient client = NULL;
  6. Sqlmapconfigparser configparser = new sqlmapconfigparser ();
  7. For (INT I =
    0; I <configlocations. length; I ++ ){
  8. Inputstream is = configlocations [I]. getinputstream ();
  9. Try {
  10. Client = configparser. parse (is, properties );
    // Parse the configuration file using sqlmapconfigparser to generate the sqlmapclientimpl object
  11. }
  12. ...
  13. Return client;
  14. }

In the above Code, call sqlmapconfigparser to parse the sqlmap configuration file sqlmap-ibatis.xml.

2) Call sqlmapconfigparser for parsing
Sqlmapconfigparser. parse (inputstream, properties props) method source code is as follows:

Java code
  1. Public sqlmapclient parse (inputstream, properties props ){
  2. If (props! = NULL) state. setglobalprops (props );
  3. Return parse (inputstream );
  4. }

The source code of the parse () method is as follows:

Java code
  1. Public sqlmapclient parse (inputstream ){
  2. ...
  3. Parser. parse (inputstream); // call nodeletparser to parse the configuration file
  4. Return state. getconfig (). getclient ();
    // Returns the sqlmapclientimpl object.
  5. ...
  6. }

3) Call nodeletparser for parsing
Nodeletparser. parse () is the core method of parsing the configuration file, which is called by sqlmapconfigparser to parse the sqlmap configuration file sqlmap-ibatis.xml.

Java code
  1. Public void parse (inputstream)
    Throws nodeletexception {
  2. Try {
  3. Document Doc = createdocument (inputstream );
  4. Parse (Doc. getlastchild (); // parse from the root node
  5. }
  6. ...
  7. }

The source code of the parse (node) method is as follows:

Java code
  1. Public void parse (node ){
  2. Path = New Path ();
  3. Processnodelet (node ,"/");
  4. Process (node, PATH );
  5. }

This method contains two important methods. processnodelet () is processed based on the XPath of the current node. The process () method is used to process node-related information (such as element, attribute, and children ).

First, let's take a look at the source code implementation of processnodelet (node, string pathstring:

Java code
  1. Private void processnodelet (node, string pathstring ){
  2. Nodelet = (nodelet) letmap. Get (pathstring );
  3. If (nodelet! = NULL ){
  4. Try {
  5. Nodelet. Process (node );
  6. }
  7. ...
  8. }
  9. }

Note: In the sqlmapconfigparser class introduction, we mentioned that the letmap attribute in nodeletparser maintains the ing between the node XPath information and the node information processing method, all mappings are added to the sqlmapconfigparser constructor. Obtain the corresponding processing method nodelet Based on the node's XPath, and then call nodelet. Process () to process the node information.

Let's take a look at the source code implementation of nodeletparser. Process (node, Path:

Java code
  1. Private void process (node, Path ){
  2. If (node instanceof element ){
  3. // Process Element Information
  4. String elementname = node. getnodename ();
  5. Path. Add (elementname );
  6. Processnodelet (node, path. tostring ());
  7. Processnodelet (node, new stringbuffer ("//"). append (elementname). tostring ());
  8. // Process attribute information
  9. Namednodemap attributes = node. getattributes ();
  10. Int n = attributes. getlength ();
  11. For (INT I =
    0; I <n; I ++ ){
  12. Node ATT = attributes. item (I );
  13. String attrname = Att. getnodename ();
  14. Path. Add ("@" + attrname );
  15. Processnodelet (ATT, path. tostring ());
  16. Processnodelet (node, new stringbuffer ("// @"). append (attrname). tostring ());
  17. Path. Remove ();
  18. }
  19. // Process children information
  20. Nodelist children = node. getchildnodes ();
  21. For (INT I =
    0; I <children. getlength (); I ++ ){
  22. Process (children. Item (I), PATH); // recursively process subnodes
  23. }
  24. Path. Add ("end ()");
  25. Processnodelet (node, path. tostring ());
  26. Path. Remove ();
  27. Path. Remove ();
  28. } Else if (node
    Instanceof text ){
  29. // Text
  30. Path. Add ("text ()");
  31. Processnodelet (node, path. tostring ());
  32. Processnodelet (node, "// text ()");
  33. Path. Remove ();
  34. }
  35. }

In this method, the element, attribute, and children information of nodes are processed sequentially, and the children information is processed recursively. When processing each node, first construct the XPath information of the current node, and then call processnodelet (node, PATH) to process the node.

4) Call sqlmapparser to parse the sqlmap ing configuration file casesql. xml.
When processing sqlmap nodes in the sqlmap configuration file sqlmap-ibatis.xml, the following nodelet is called for processing:

Java code
  1. Protected void addsqlmapnodelets (){
  2. Parser. addnodelet ("/sqlmapconfig/sqlmap ",
    New nodelet (){
  3. Public void process (node)
    Throws exception {
  4. ...
  5. Properties attributes = nodeletutils. parseattributes (node, state. getglobalprops ());
  6. String resource = attributes. getproperty ("resource ");
  7. String url = attributes. getproperty ("url ");
  8. ...
  9. New sqlmapparser (state). parse (Reader );
    // Call sqlmapparser to parse the sqlmap ing File
  10. }
  11. }
  12. });
  13. }

Sqlmapparser's parse () method is implemented as follows:

Java code
  1. Public void parse (inputstream)
    Throws nodeletexception {
  2. Parser. parse (inputstream); // call nodeletparser to parse the configuration file
  3. }

Similar to the above sqlmapconfigparser resolution method, both call nodeletparser to parse the configuration file. The difference is that these two classes are used to parse different configuration files (sqlmapconfigparser is used to parse the sqlmap configuration file, sqlmapparser is used for the sqlmap ing file). Therefore, when the respective constructors insert letmap, the key used is the XPath of the node in the configuration file.

5) Call sqlstatementparser to generate mappedstatement.
When the select node of the sqlmap ing file is parsed, sqlstatementparser is called to generate mappedstatement.

Java code
  1. Protected void addstatementnodelets (){
  2. ...
  3. Parser. addnodelet ("/sqlmap/select ",
    New nodelet (){
  4. Public void process (node)
    Throws exception {
  5. Statementparser. parsegeneralstatement (node,
    New selectstatement ());
  6. }
  7. });

The implementation of sqlstatementparser. parsegeneralstatement () is not described here. The main purpose is to build mappedstatement and inject the parsed information of the configuration file into xmlparserstate.

Summary
The core objective of ibatis Initialization is to build the sqlmapclientimpl object. The main idea is as follows:
1. Construct the nodeletparser Configuration File Parsing class, which maintains the XPath ing between the node XPath and the corresponding processing method, and provides a common processing method for the node.
2. sqlmapconfigparser and sqlmapparser Add the XPath ing between the node XPath and the corresponding processing method to nodeletparser In the constructor.
3. The configuration file is parsed recursively. The XPath information of the current node is generated first, and the corresponding processing method is obtained and executed from nodeletparser.
4. The data generated by each node is uniformly injected into xmlparserstate throughout the parsing process, and the sqlmapclientimpl object is obtained and returned through xmlparserstat.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.