In the article "Easy to MyBatis series (ii)---configuration introduction (mybatis source code)" We through the MyBatis source of simple analysis, can be seen in the MyBatis configuration file, under the Config root node, Configurable 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 can be specified by using the URL property < Properties Resource= "Dbconfig.properties" ></properties> 4- -5 <!--method Two: Directly configured as XML-- > 6 <properties> 7 <property name= "Driver" value= "Com.mysql.jdbc.Driver"/> 8 < Property name= "url" value= "Jdbc:mysql://localhost: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 the properties file for the database configuration is not specified above, this can be configured directly here < Property name= "Driver" value= "Com.mysql.jdbc.Driver"/> <property name= "url" value= "jdbc:mysql://localhost:330 6/test1 "/> <property name=" username "value=" root "/> <property name=" password "value=" root "/> -<!--above specifies the database configuration file, the configuration file also corresponds to the corresponding four properties--<property name= "Driver" value= "${ Driver} "/> <property name=" url "value=" ${url} "/> <property name=" username "value=" ${username} " /> <property name= "password" value= "${password}"/> </dataSource> </environment& Gt <!--I specify a environment--<environment id= "Test" > <transactionmanager type= "JDBC"/> <da Tasource type= "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"/&G T <property name= "Password" value= "root"/> </dataSource> </environment> </environments>
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//xml 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, the private void parseconf Iguration (XNode root) {One-try {12//Parse properties Element propertieselement (Root.evalnode ("Prope Rties ")); 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 databaseidproviderelement (Root.evaLnode ("Databaseidprovider")); Typehandlerelement (Root.evalnode ("typehandlers")); Mapperelement (Root.evalnode ("mappers")); (Exception e) {builderexception "Error parsing SQL Mapper Configuration. Cause: "+ E, E); 26} 27} 28 29 30//The following is a look at the specific methods of resolving properties. private void Propertieselement (XNode context) t Hrows Exception {+ if (context! = null) {33//The name of the child node and the Value property are set into the Properties object 34// To note the order, the XML configuration takes precedence, the externally specified properties are configured next to the properties defaults = Context.getchildrenasproperties (); 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 Elem ENT cannotSpecify both a URL and a resource based property file reference. Specify one or the other. "); 42} 43//Set the parsed properties file into the Properties object (Resource! = null) {Defaul Ts.putall (Resources.getresourceasproperties (Resource)); Defaults.putall} else if (URL! = null) {resources.geturlasproperties (URL)); 48} 4 9///The configured Properties property in the Configuration object and the fused//configuration of the newly resolved object will load all the node elements of the parsed MyBatis configuration file, which will be frequently mentioned later Object 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 (); VARs! = null) {Defaults.putall (VARs); 56} 57//Put the parse configuration Propertis object Set Into the parser, since the Parser.setvariables (defaults) may be used later; Configuration.setvariables (defaults) of//set into the configuration object; 61} 62} 63 64//below take a look at the method of parsing enviroments element nodes. environmentselement (XNode context) throws Exception {66 if (context = null) {environment = = NULL) {68//resolves the value of environments node's default property 69 Example: <environments default= "Development" > Environment = context.getstringattribut E ("Default"); 71} 72//Recursive parsing Environments subnode for (XNode Child:context.getChildren ()) {74 <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= "Developme NT "><environment id=" development ">...</environment><environment id=" test ">...</ Environments> 77//means that we can correspond to multiple environments, such as development environment, test environment, etc., by environments's default property to select the corresponding enviroment 78 String id = child.getstringattribute ("id"); 79//Isspecial is based on the default property of environments to select the corresponding enviroment if (isspecifiedenvironment (ID)) {81 Transactions, there are two types of mybatis: JDBC and MANAGED, which are configured to use JDBC directly, configured as MANAGED to host the transaction to the container, and the Transactionfacto Ry 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) 87. Transactionfactory (Txfactory), DataSource (DataSource); 89//The usual, the datasource will be set into the Configuration object Configuration.setenvironment (environmen Tbuilder.build ()); 91} 92} 93} 94} 95 96//below look at the analytic method of DataSource datasourcefactory Datasourceelement (XNode context) throws Exception { 98 if (context! = null) {//datasource connection pool, String type = Context.getstringattribute ("type"); 101//child node name, Value property set into a Properties object 102 Properties Props = Context.getchildrenasprop Erties (); 103//Create dataSourceFactory104 Datasourcefactory factory = (datasourcefactory) resolveclass (type). newinstance (); factory.setproperties (props); 106 return factory;107}108 throw new Builderexception ("Environment declaration requires a datasourcefactory."); 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); Generictokenparser parser = new Generictokenparser ("${", "}", handler); return Parser.parse (string); } private static class Variabletokenhandler implements Tokenhandler { private Properties variables; Public Variabletokenhandler (Properties variables) { this.variables = variables; } public string Handletoken (string content) { if (variables! = null && variables.containskey (content)) { return Variables.getproperty (content); } 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) [Turn]