Through the simple analysis of the MyBatis source code, we can see that in the mybatis configuration file, under the Config root node, you can configure properties, typealiases, Plugins, Objectfactory, Objectwrapperfactory, settings, environments, Databaseidprovider, typehandlers, mappers these nodes. Then this time, you will first introduce the properties node and the Environments node.
In order to enable everyone to better read the MyBatis source code, I will give you a simple example of the use of properties.
1 <configuration> 2 <!--method One: Specify the properties profile externally, and in addition to the Resource property designation, URL 3 <properties can be specified via the URL property resource = "Dbconfig.properties" ></properties> 4--5 <!--method Two: Directly configured to XML--6 <properties> 7 <property name= "Driver" value= "Com.mysql.jdbc.Driver"/> 8 <property name= "url" value= "Jdbc:mysql://localhos T:3306/test1 "/> 9 <property name=" username "value=" root "/>10 <property name=" password "value=" root "/>11 </properties>
So, if I use both of these methods, which one is the preferred method?
when both of these methods are XML configured first, the externally specified properties configuration is followed. As for why, the next source analysis will mention, please pay attention to.
Let's take a look at the use of the Envirements element node:
<environments default= "Development" > <environment id= "Development" > <transactionmanager type= "JDBC" /> <datasource type= "Pooled" > <!-- If there is no properties file specified for the database configuration, So this can be configured directly here <property name= "Driver" value= "Com.mysql.jdbc.Driver"/> & nbsp <property name= "url" value= "Jdbc:mysql://localhost:3306/test1"/> <property Name= "username" value= "root"/> <property name= "password" value= "root"/> --!--The database configuration file is specified above, the configuration file also corresponds to these four properties--<property name= "Driv Er "value=" ${driver} "/> <property name=" url "value=" ${url} "/> <property name=" username "value= "${username}"/> <property name= "password" value= "${password}"/> </dataSource> < /environment> <!--I'llSpecify a environment--<environment id= "Test" > <transactionmanager type= "JDBC"/> <datasource t Ype= "Pooled" > <property name= "Driver" value= "Com.mysql.jdbc.Driver"/> <!--is not the same as the above URL-- <property name= "url" value= "Jdbc:mysql://localhost:3306/demo"/> <property name= "username" value= "root" /> <property name= "password" value= "root"/> </dataSource> </environment> </env Ironments>
environments element nodes can be configured with more than one environment child node, how to understand it?
If our system's development environment is different from the database used in the formal environment (this is for sure), then you can set up two environment, two IDs for the development environment (DEV) and the formal environment (final), Then you can select the corresponding environment by configuring the default property of environments, for example, if I configure the value of the Deault property of environments to Dev, then the environment of Dev is selected. As to how this is achieved, the following source will speak.
OK, the above simple to introduce you to the properties and environments configuration, then formally began to look at the source code:
Last time we said MyBatis is through xmlconfigbuilder this class in parsing mybatis configuration file, then this time to see Xmlconfigbuilder for properties and environments parsing:
Xmlconfigbuilder:
1 public class Xmlconfigbuilder extends Basebuilder { 2 3 private boolean parsed; 4//XM L Parser 5 Private Xpathparser parser; 6 private String environment; 7 8//The last time I talked about this method is to parse the element node that can be configured in the MyBatis configuration file 9//The first thing to see today is the Properties node and the Environments node privat e void parseconfiguration (XNode root) {One-try {12//Parse properties element propertieselement (root . Evalnode ("Properties")); Issue #117 Read Properties First typealiaseselement (Root.evalnode ("typealiases")); Pluginelement (Root.evalnode ("plugins")); Objectfactoryelement (Root.evalnode ("objectfactory")); Objectwrapperfactoryelement (Root.evalnode ("objectwrapperfactory")); Settingselement (Root.evalnode ("Settings")); 19//Parse environments element Environmentselement (Root.evalnode ("Environments")); Read it after Objectfactory and objectwrapperfactory issue #631 21 Databaseidproviderelement (Root.evalnode ("Databaseidprovider")); Typehandlerelement (Root.evalnode ("typehandlers")); Mapperelement (Root.evalnode ("mappers")); (Exception e) {builderexception "Error parsing SQL Mapper Configuration. Cause: "+ E, E); &NBSP;} 29 30///The following is a look at the specific methods of resolving properties. private void Prop Ertieselement (XNode context) throws Exception {+ if (context! = null) {33//Set the name of the child node and the Value property into P Roperties Object 34//Here you can note the order, the XML configuration takes precedence, the externally specified properties configuration is followed by the properties defaults = Context.getchildrenas Properties (); 36//Get the value of the resource property on the Properties node PNs String resource = Context.getstringattribute ("resource"); 38//Get the value of the URL property on the Properties node, resource and URL cannot be configured at the same time as the String URL = context.getstringattribute ("url"); if (resource! = NULL && URL! = null){$ throw new Builderexception ("The properties element cannot specify both a URL and a resource based Propert Y file Reference. Specify one or the other. "); } 43//Set the parsed properties file into the Properties object (Resource! = NULL ) { defaults.putall (resources.getresourceasproperties (Resource)); 46 } else if (URL! = null) { defaults.putall (resources.geturlasproperties (URL) ); } 49//combines the configured Properties property in the configuration object with the newly resolved fusion of the//configurat Ion this object will load all the node elements of the parsed MyBatis configuration file, and will refer to this object again and again 51//Since the configuration object has a series of get/set methods, does that indicate that we can use Java code to configure directly? 52//The answer is yes, but with configuration file configuration, the advantage is self-evident that the Properties VARs = Configuration.getvariables (); if (VARs! = null) { defaults.putall (VARs); &nbSp &NBSP;} 57//Put the parse configuration Propertis object set into the parser, because it may be used later par Ser.setvariables (defaults); //set Configuration Objects configuration.setvariables (defaults); }   enviroments;} 63 64//below take a look at the methods of parsing the nodes of the environ. Mentselement (XNode context) throws Exception {environment if (context! = null) {if (= = null) { 68//Parse the value of the default property of the Environments node 69//For example: <environments default= "Development" > 70 Environment = Context.getstringattribute ("Default"); &NBSP;} 72//Recursive parsing environments child node for (XNode Child:cont Ext.getchildren ()) {//<environment id= "development", only the enviroment node has an id attribute, what does this attribute do? The//environments node can have multiple environment sub-nodes 76 Similar to this: <environments default= "Development" ><environment id= "development" >...</environment> <environment id= "Test" >...</environments> 77//means we can correspond to multiple environments, such as development environment, test environment, etc., by environments DEFA Ult property to select the corresponding enviroment String id = child.getstringattribute ("id"); //isspecial is based on the default property of environments to select the corresponding enviroment if (Isspecifiedenvironment (ID ) {81///transaction, MyBatis has two types: JDBC and MANAGED, and JDBC is configured to use JDBC directly, configured as MANAGED to host the transaction to the container, 82 Transactionfactory txfactory = transactionmanagerelement (Child.evalnode ("TransactionManager")); The//enviroment node below is the DataSource node, parsing the DataSource node (below will be posted on the specific method of parsing datasource) DataS Ourcefactory dsfactory = datasourceelement (Child.evalnode ("DataSource")); DataSource DataSource = Dsfactory.getdatasource (); Environment.builder ENVIRONMENTBUIlder = new Environment.builder (ID) &NBSP ; .transactionfactory (txfactory) &NBS P .datasource (DataSource); 89//The usual, the datasource will be set into the configuration object &N Bsp configuration.setenvironment (Environmentbuilder.build ()); }   ;} &nb Sp &NBSP;} 94 &NBSP;} 95 96//See below for an analysis of DataSource's resolution. Private Datasourcefactory Datasourceelement ( XNode context) throws Exception {98 if (context! = null) {Connection pool of//datasource Type = Context.getstringattribute ("type"); 101//child node name, Value property set into a Properties object 102 properties Props = Context.getchildrenaspropertiES (); 103//Create dataSourceFactory104 Datasourcefactory factory = (datasourcefactory) resolveclass (typ e). newinstance (), factory.setproperties (props); 106 Return Factory ; 107 }108 throw new Builderexception ("Environment declaration requires a DATASOURCEFAC Tory. "); 109 } 110}
Through the above to the MyBatis source code interpretation, I believe that we have a deep understanding of the configuration of MyBatis.
There is also a problem, we see above, in the configuration of DataSource when the use of ${driver} This expression, this form is how to parse? In fact, it is through Propertyparser this class parsing:
Propertyparser:
/** * This class parses ${} This form of expression */public class Propertyparser { public static String parse ( String string, Properties variables) { variabletokenhandler handler = new Variabletokenhandler (variables); nbsp generictokenparser parser = new Generictokenparser ("${", "}", Handler); return Parser.parse (string); } private static Class Variabletokenhandler implements Tokenhandler { private Properties variabl Es public Variabletokenhandler (Properties variables) { this.variables = variables; & nbsp;} public string Handletoken (string content) { if (variables! = null && variables.co Ntainskey (content)) { return variables.getproperty (content), } &nbs P return "${" + Content + "}"; } }}
Well, the above is for the properties and environments element node analysis, the more important are in the source code for the comment. By the end of this article, the next article will continue to analyze the configuration of the other nodes.
?
MyBatis series (three)---configuration detailed properties and environments (MyBatis source article)