MYBATIS3 Source Analysis (02)-Load Configuration-xmlconfigbuilder

Source: Internet
Author: User
Tags vars
The role of configuration class in MyBatisThe configuration class holds configuration information for all MyBatis. That is to say, all configuration information in Mybaits-config.xml and Usermapper.xml can find the appropriate information in the Configruation object. Typically, MyBatis creates only one Configration object during the run, and the configuration information can no longer be modified. How to configure MyBatis can look at this document: http://mybatis.org/mybatis-3/zh/configuration.html
Properties of configurationThe attributes of configuration are mainly divided into two main parts: the configuration read from the Mybatis-config.xml from the Mapper configuration file or mapper annotation read the configuration of the two parts of the corresponding relationship between the properties and configuration corresponding properties from the Mybatis-config.xml file
  protected Boolean saferowboundsenabled = false;
  Protected Boolean saferesulthandlerenabled = true;
  protected Boolean mapunderscoretocamelcase = false;
  Protected Boolean aggressivelazyloading = true;
  Protected Boolean multipleresultsetsenabled = true;
  protected Boolean Usegeneratedkeys = false;
  Protected Boolean Usecolumnlabel = true;
  Protected Boolean cacheenabled = true;
  protected Boolean callsettersonnulls = false;
  protected String Logprefix; Protected Class?
  Extends log> Logimpl;
  protected Localcachescope localcachescope = localcachescope.session;
  protected Jdbctype jdbctypefornull = Jdbctype.other; protected set<string> lazyloadtriggermethods = new Hashset<string> (arrays.aslist (new string[] {"Equals", "
  Clone "," Hashcode "," toString "}));
  protected Integer defaultstatementtimeout;
  protected Executortype defaultexecutortype = executortype.simple;

  protected Automappingbehavior automappingbehavior = automappingbehavior.partial;Protected Properties Variables = new properties ();
  protected Objectfactory objectfactory = new Defaultobjectfactory ();
  protected Objectwrapperfactory objectwrapperfactory = new Defaultobjectwrapperfactory ();

  protected Mapperregistry mapperregistry = new Mapperregistry (this);
  protected Boolean lazyloadingenabled = false;

  protected Proxyfactory proxyfactory;
  Protected final Interceptorchain Interceptorchain = new Interceptorchain ();
  Protected final Typehandlerregistry typehandlerregistry = new Typehandlerregistry ();
  Protected final Typealiasregistry typealiasregistry = new Typealiasregistry (); Protected final Languagedriverregistry languageregistry = new Languagedriverregistry ();
The above properties can be said to have been read by the Mybatis-config.xml file. For example, the setting configuration in a file
<settings>
  <setting name= "cacheenabled" value= "true"/> <setting name=
  "lazyloadingenabled" Value= ' true '/>
  <setting name= ' multipleresultsetsenabled ' value= ' true '/> <setting ' name= '
  Usecolumnlabel "value=" true "/>
  <setting name=" Usegeneratedkeys "value=" false "/> <setting name=
  "Automappingbehavior" value= "PARTIAL"/>
  <setting name= "Defaultexecutortype" value= "simple"/>
  <setting name= "Defaultstatementtimeout value="/> <setting name= "
  defaultfetchsize" value= "100" >
  <setting name= "saferowboundsenabled" value= "false"/> <setting
  "Name=" Mapunderscoretocamelcase "value=" false "/> <setting name=" Localcachescope "value=" session
  "/>
  <setting name= "Jdbctypefornull" value= "other"/> <setting name=
  "Lazyloadtriggermethods" equals , clone,hashcode,tostring "/>
</settings>

Look at the contents of the configuration and the name of the property in the configuration, you probably know the corresponding relationship. Believe that after the content of the analysis will not be too complicated. Properties read from the mapper configuration fileThe following properties are read from the mapper configuration file
  Protected final map<string, mappedstatement> mappedstatements = new Strictmap<mappedstatement> ("Mapped Statements Collection ");
  Protected final map<string, cache> caches = new Strictmap<cache> ("caches collection");
  Protected final map<string, resultmap> resultmaps = new strictmap<resultmap> ("Result Maps collection");
  Protected final map<string, parametermap> parametermaps = new Strictmap<parametermap> ("Parameter Maps Collection ");
  Protected final map<string, keygenerator> keygenerators = new Strictmap<keygenerator> ("Key generators Collection ");
One of the most important and relatively complex is the following two (mapper configuration files are also primarily configured with these two items): The Mappedstatements property, which holds the Select/update/insert/delete node information in all mapper configuration files. The property type is a map,key sql corresponding id,mappedsatement is a Java object that holds a Select/update/insert/delete node information. The Resultmaps property, which holds the Resultmap node in all mapper configuration files. The mapper configuration file is also primarily configured with SELECT/UPDATE/INSERT/DELETE/RESULTMAP nodes.

Configuration Loading ProcessFor mybatis-config.xml configuration files and mapper configuration files, MyBatis is also resolved by two corresponding classes. Xmlconfigbuilder parsing mybatis-config.xml Configuration to Configuration Xmlmapperbuilder parsing mapper configuration file configuration into configuration
Xmlconfigbuilder.parse () method

To get configuration code through Sqlsessionfactory

Sqlsessionfactory sqlsessionfactory=new Sqlsessionfactorybuilder (). Build (IS);
System.out.println (Sqlsessionfactory.getconfiguration ());

Then look at the Sqlsessionfactorybuilder.build () method:

 Public Sqlsessionfactory builds (InputStream inputstream) {return build (InputStream, NULL, NULL); Sqlsessionfactory Build (InputStream InputStream, String Environment) {return build (InputStream, Environme
  NT, NULL); Sqlsessionfactory Build (InputStream InputStream, properties properties) {return build (InputStream, NULL,
  properties);
      Sqlsessionfactory Build (InputStream InputStream, String Environment, properties properties) {try {
      Xmlconfigbuilder parser = new Xmlconfigbuilder (InputStream, Environment, properties);
    It can be seen from here that Xmlconfigbuilder.parse () returns a configuration object return build (Parser.parse ());
    catch (Exception e) {throw exceptionfactory.wrapexception ("Error building sqlsession.", e);
      finally {errorcontext.instance (). reset ();
      try {inputstream.close (); The catch (IOException e) {//intentionally ignore.
      Prefer previous error. }} public Sqlsessionfactory build (Configuration config) {return new Defaultsqlsessionfactory (config); }


Load specific configuration

Public Configuration Parse () {if (parsed) {throw new Builderexception ("Each xmlconfigbuilder can only be used
    Once. ");}
    parsed = true;
    Parseconfiguration (Parser.evalnode ("/configuration"));
  return configuration; ///Load from XML configuration file to configuration object private void Parseconfiguration (XNode root) {try {//Load properties node, typically defined Some variable propertieselement (Root.evalnode ("Properties"));
      Issue #117 Read Properties I//load alias Typealiaseselement (Root.evalnode ("typealiases"));
      Interceptor Pluginelement (Root.evalnode ("plugins"));
      Objectfactoryelement (Root.evalnode ("objectfactory"));
      
      Objectwrapperfactoryelement (Root.evalnode ("objectwrapperfactory"));
      Settingselement (Root.evalnode ("Settings")); Environmentselement (Root.evalnode ("Environments")); Read it after Objectfactory and objectwrapperfactory issue #631 databaseidproviderelement root.evalnode ("Database

      Idprovider ")); Load the mapper configuration file, the most importantThere are two: one is the definition of SQL, one is Resultmap typehandlerelement (Root.evalnode ("typehandlers"));
    Mapperelement (Root.evalnode ("mappers")); The catch (Exception e) {throw new Builderexception ("Error parsing SQL Mapper Configuration.
    Cause: "+ E, E); }
  }


Load Properties node

   private void Propertieselement (XNode) throws Exception {if (context!= null) {//Load properties under Property child nodes first
      Properties defaults = Context.getchildrenasproperties ();
      String resource = Context.getstringattribute ("resource");
      String url = context.getstringattribute ("url"); You cannot set both the Resource property and the URL property if (Resource!= null && URL!= null) {throw new Builderexception ("the Prop  erties element cannot specify both a URL and a resource based property file reference.
      Please specify one or the other. ");}
      if (resource!= null) {//will overwrite the configuration of the child node Defaults.putall (resources.getresourceasproperties (Resource));
      else if (URL!= null) {//will overwrite the configuration defaults.putall (resources.geturlasproperties (URL) of the child node);
      Properties VARs = Configuration.getvariables ();
      if (VARs!= null) {Defaults.putall (VARs);
      } parser.setvariables (defaults); Set the list of variables to Configuration.setVariables (defaults); }
  }

From this method you can see that the configuration rules can be set URL or resource property from the external file to load a properties file can be configured through the property child node, if the child node attribute key and external file key Repeat, the child node will be covered Programmatically defined attributes are finally loaded, with the highest precedence:
Public sqlsessionfactory Build (InputStream InputStream, properties properties)

Properties Configuration Sample

<properties resource= "Org/mybatis/example/config.properties" >
  <property name= "username" value= "dev_" User "/>
  <property name=" Password value= "F2fa3!33tyyg"/>
</properties>

The main load here is to use the following configuration as a variable!


Load alias

private void Typealiaseselement (xnode parent) {if (parent!= null) {for (XNode Child:parent.getChildren ()) { if ("Package". Equals (Child.getname ())) {//package way, rarely used, skip String typealiaspackage = Child
          . Getstringattribute ("name");
        Configuration.gettypealiasregistry (). registeraliases (Typealiaspackage);
          else {String alias = Child.getstringattribute ("Alias");
          String type = Child.getstringattribute ("type");
            try {class<?> clazz = resources.classforname (type);
            if (alias = = null) {Typealiasregistry.registeralias (clazz);
            else {//load into alias Registry Typealiasregistry.registeralias (alias, Clazz); (ClassNotFoundException e) {throw new Builderexception ("Error registering Typealias for") "+ Alias +" '.
          Cause: "+ E, E); }
        }
      }
    }
  }

Look again typealiasregistry source code, found that MyBatis has been defined a lot of aliases, easy to configure later
Public Typealiasregistry () {Registeralias ("string", String.class);
    Registeralias ("byte", Byte.class);
    Registeralias ("Long", long.class);
    Registeralias ("short", short.class);
    Registeralias ("int", integer.class);
    Registeralias ("integer", Integer.class);
    Registeralias ("Double", double.class);
    Registeralias ("float", float.class);

    Registeralias ("boolean", Boolean.class);
    Registeralias ("byte[]", byte[].class);
    Registeralias ("long[]", long[].class);
    Registeralias ("short[]", short[].class);
    Registeralias ("int[]", integer[].class);
    Registeralias ("integer[]", integer[].class);
    Registeralias ("double[]", double[].class);
    Registeralias ("float[]", float[].class);

    Registeralias ("boolean[]", boolean[].class);
    Registeralias ("_byte", Byte.class);
    Registeralias ("_long", Long.class);
    Registeralias ("_short", Short.class);
    Registeralias ("_int", Int.class);
    Registeralias ("_integer", Int.class); Registeralias ("_douBle ", double.class);
    Registeralias ("_float", Float.class);

    Registeralias ("_boolean", Boolean.class);
    Registeralias ("_byte[]", byte[].class);
    Registeralias ("_long[]", long[].class);
    Registeralias ("_short[]", short[].class);
    Registeralias ("_int[]", int[].class);
    Registeralias ("_integer[]", int[].class);
    Registeralias ("_double[]", double[].class);
    Registeralias ("_float[]", float[].class);

    Registeralias ("_boolean[]", boolean[].class);
    Registeralias ("date", Date.class);
    Registeralias ("decimal", bigdecimal.class);
    Registeralias ("BigDecimal", Bigdecimal.class);
    Registeralias ("BigInteger", Biginteger.class);

    Registeralias ("Object", Object.class);
    Registeralias ("date[]", date[].class);
    Registeralias ("decimal[]", bigdecimal[].class);
    Registeralias ("bigdecimal[]", bigdecimal[].class);
    Registeralias ("biginteger[]", biginteger[].class);

    Registeralias ("object[]", object[].class);
Registeralias ("Map", Map.class);    Registeralias ("HashMap", Hashmap.class);
    Registeralias ("list", List.class);
    Registeralias ("ArrayList", Arraylist.class);
    Registeralias ("collection", Collection.class);

    Registeralias ("iterator", iterator.class);
  Registeralias ("ResultSet", Resultset.class); }

There is also a way to load class by using an alias
   Public <T> class<t> Resolvealias (String string) {
    try {
      if (string = = null) return null;
      String key = String.tolowercase (Locale.english); Issue #748
      class<t> value;
      if (Type_aliases.containskey (key)) {
        //if it is an alias, return
        value = (class<t>) type_aliases.get (key) directly from the registry;
      } else {
        value = (class<t>) resources.classforname (string);
      }
      return value;
    } catch (ClassNotFoundException e) {
      throw new typeexception ("could not resolve type alias" + String + "".  ) Cause: "+ E, E);
    }
  }

Load Mapper configuration file
 private void Mapperelement (xnode parent) throws Exception {if (parent!= null) {for (XNode Child:parent.get Children ()) {if ("package". Equals (Child.getname ())) {String mapperpackage = Child.getstringattribute ("
          Name ");
        Configuration.addmappers (Mapperpackage);
          else {String resource = Child.getstringattribute ("resource");
          String url = child.getstringattribute ("url");
          String Mapperclass = Child.getstringattribute ("class"); if (resource!= null && URL = null && Mapperclass = null) {errorcontext.instance (). Resource
            (Resource);
            InputStream InputStream = resources.getresourceasstream (Resource); Xmlmapperbuilder mapperparser = new Xmlmapperbuilder (inputstream, configuration, res, parsed by Xmlmapperbuilder object)
            Ource, Configuration.getsqlfragments ());
          Mapperparser.parse (); else if (resource = null && URL!= null && Mapperclass = = null) {errorcontext.instance (). resource (URL);
            InputStream inputstream = resources.geturlasstream (URL); Load Xmlmapperbuilder mapperparser = new Xmlmapperbuilder (inputstream, configuration, URL, Xmlmapperbuilder object resolution)
            , configuration.getsqlfragments ());
          Mapperparser.parse (); else if (resource = = null && URL = null && mapperclass!= null) {class<?> Mapperinte
            Rface = Resources.classforname (Mapperclass);
          Configuration.addmapper (Mapperinterface); else {throw new Builderexception ("A mapper element may only specify A URL, resource or class, but no more than one. ");}}}}


A mapper configuration file is eventually loaded into the configuration object by Xmlmapperbuilder object resolution. The parsing process of Xmlmapperbuilder is similar to Xmlconfigbuilder parsing process, and then analyzed in detail later.


load Other configuration items There are some configuration items not mentioned here, such as: Plug-in/Interceptor, object factory, setting items. These loading are relatively simple, as long as the heart can be seen to understand. In the future analysis of the code process, you will certainly see the configuration here, and then further study, but you can be sure that the configuration in many cases are using the default value.


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.