I. Overview
Second, create
The creation of a MyBatis data source is a little bit tortuous.
1. The creation process of the data source;
2. What data sources are supported by MyBatis, that is, which valid parameters can be written by the type attribute of the datasource tag?
To figure out these problems, the entire parsing process for MyBatis is clear, and the same can be applied to any configuration resolution.
Start from Sqlsessionfactorybuilder to trace the creation of DataSource. Sqlsessionfactorybuilder 9 constructs the method, in which the character stream 4 constructs the method one by one corresponding byte stream 4 constructs the method, all is resolves the mybatis-config.xml configuration file to the configuration object, the final guidance build (Configuration configuration) for sqlsessionfactory construction.
Configuration file in the build (InputStream, env, Properties) in the construction method to parse, InputStream and Reader in addition to the same flow, inputstream, for example, to trace the source code.
Public sqlsessionfactory Build (InputStream InputStream, String Environment, properties properties) {try { // Parsing objects for the Mybatis-config.xml file //encapsulating the Configuration object in Xmlconfigbuilder//The parse is not really occurring at this time, but the prerequisites for parsing are ready Xmlconfigbuilder parser = new Xmlconfigbuilder (InputStream, Environment, properties); The invocation of Parser.parse () signifies that the configuration in the parse's start//Mybatis-config.xml will be parsed into a runtime object encapsulated in the configuration return build ( Parser.parse ());} catch (Exception e) { throw exceptionfactory.wrapexception ("Error building sqlsession.", e);} finally { Errorcontext.instance (). reset (); try {inputstream.close (); } catch (IOException e) {//intentionally ignore. Prefer previous error.}} }
In Xmlconfigbuilder further tracing, the question is eventually retained on the Resolveclass method of its parent class Basebuilder, which finds the bytecode of the data source factory.
Public Configuration Parse () {if (parsed) {throw new Builderexception ("Each xmlconfigbuilder can is only is used on CE. ");} parsed = true;//Mybatis-config.xml is the root node of the configuration//configuration file is the parse entry parseconfiguration (Parser.evalnode ("/ Configuration ")); return configuration; private void Parseconfiguration (XNode root) {try {propertieselement (Root.evalnode ("Properties"));//issue #11 7 Read Properties First typealiaseselement (Root.evalnode ("typealiases")); Pluginelement (Root.evalnode ("plugins")); Objectfactoryelement (Root.evalnode ("objectfactory")); Objectwrapperfactoryelement (Root.evalnode ("objectwrapperfactory")); Settingselement (Root.evalnode ("Settings")); The environment node contains the transaction and connection pool nodes Environmentselement (Root.evalnode ("Environments")); Read it after Objectfactory and objectwrapperfactory issue #631 databaseidproviderelement (Root.evalnode ("Databasei Dprovider ")); Typehandlerelement (Root.evalnode ("typehandlers")); MApperelement (Root.evalnode ("mappers")); } catch (Exception e) {throw new Builderexception ("Error parsing SQL Mapper Configuration. Cause: "+ E, E); }} private void Environmentselement (XNode context) throws Exception {if (context! = null) {if (environment = = NULL) {//If the called build does not have an incoming environment id//then the default environment, the default= "environment_id" of the Environments label configuration Environm ent = Context.getstringattribute ("Default"); } for (XNode Child:context.getChildren ()) {String id = child.getstringattribute ("id"); if (Isspecifiedenvironment (ID)) {transactionfactory txfactory = transactionmanagerelement (Child.evalnode ("Transa Ctionmanager ")); Data source factory parsing//Here is the focus, data source Factory lookup Datasourcefactory dsfactory = datasourceelement (Child.evalnode ("DataSource")); Factory mode, generate the corresponding data source DataSource DataSource = Dsfactory.getdatasource (); Environment.builder Environmentbuilder = new Environment.builder (ID). transactIonfactory (txfactory). DataSource (DataSource); Configuration.setenvironment (Environmentbuilder.build ()); }}}} private Datasourcefactory Datasourceelement (XNode context) throws Exception {if (context! = NULL) {//DataSource property of the label type String type = Context.getstringattribute ("type"); Parse DataSource label Sub-label <property name= "" value= "" >//is actually the data source configuration information, URL, driver, username, password and other Properties PR OPS = Context.getchildrenasproperties (); Resolveclass: Find the Factory class object in Xmlconfigbuilder's parent class Basebuilder//This is the focus datasourcefactory factory = (datasourcefacto ry) Resolveclass (type). newinstance (); Factory.setproperties (props); return factory; } throw new Builderexception ("Environment declaration requires a datasourcefactory."); }
In the parent class without prying into the focus, go to its instance properties typealiasregistry in order to actually do the lookup process.
Protected class<?> Resolveclass (String alias) { if (alias = = null) return null; try { //do a check, go to return Resolvealias (alias), } catch (Exception e) { throw new builderexception ("Error Resolving class. Cause: "+ E, E); } } Protected class<?> Resolvealias (String alias) {///Basebuilder instance Properties//Instance properties: Protected Final Typealiasregistry Typealiasregistry; Return Typealiasregistry.resolvealias (alias); } <span style= "Font-family:simsun; Background-color:rgb (255, 255, 255); " > </span>
The typealiasregistry is actually a KV match in a map.
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)) {//private final map<string, class<?>> type_aliases = new hashmap< String, class<?>> ();//Type_aliases is an instance property, type is a map value = (class<t>) type_aliases.get (key); } else { value = (class<t>) resources.classforname (string); } return value; } catch (ClassNotFoundException e) { throw new typeexception ("Could not resolve type alias '" + string + "'). Cause: "+ E, E); } }
So the question is, when did the factory class be registered with the map?
In fact, before the parse parsing configuration file was called in the Sqlsessionfactorybuilder build (InputStream, env, propeerties) method, we ignored an important piece of code.
View the procedure for creating a xmlconfigbuilder, which, based on the rules initialized in the inheritance, will create a configuration object in the parent class Basebuilder construction method. In the construction of the configuration object, some important parameters in the framework will be registered.
public Xmlconfigbuilder (inputstream inputstream, String Environment, Properties props) {//GO this (new Xpathparser (InputStream, True, props, New Xmlmapperentityresolver ()), environment, props); } private Xmlconfigbuilder (xpathparser parser, String environment, Properties props) {//Transpose Parent class construction method//The final one is the direct new Co Nfiguration () The property passed into the parent class//Configuration Typealiasregistry will register the data source factory super (new Configuration ()); Errorcontext.instance (). Resource ("SQL Mapper Configuration"); This.configuration.setVariables (props); this.parsed = false; this.environment = environment; This.parser = parser; }
Public abstract class Basebuilder { protected final configuration configuration; Protected final typealiasregistry typealiasregistry; Protected final typehandlerregistry typehandlerregistry; Public basebuilder (Configuration configuration) { this.configuration = configuration;// Typealiasregistry from configuration//is a reasonable explanation of the typealiasregistry to find the data source factory This.typealiasregistry = This.configuration.getTypeAliasRegistry (); This.typehandlerregistry = This.configuration.getTypeHandlerRegistry (); }
At this point, the data source creation ends. Let's take a look at how to use it.
Third, detailed1. Mybatis DataSource Structure
2. MyBatis JNDI
MyBatis Jndi has been analyzed before the source code, which is not analyzed here, the original link: Click to open the link
3. MyBatis unpooled
MyBatis unpooled The idea of creating a data source, first create a data source factory with the default construction method (at which time unpooled DataSource is created). The configuration information for the data source in Mybatis-config.xml is passed through SetProperties to the factory and then through the factory Getdatasource. Look back at this section of the source code.
The result is that the data source factory is instantiated with a simple reflection using the default parameterless construction method, where the unpooled data source object is also instantiated in the data source factory.
Not to be continued!
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
"MyBatis" MyBatis data stream code profiling (JNDI, pooled, unpooled)