ホームページ  >  記事  >  Java  >  Mybatisシリーズ徹底解説(3) ~プロパティと環境の詳細設定(mybatisソースコード)

Mybatisシリーズ徹底解説(3) ~プロパティと環境の詳細設定(mybatisソースコード)

黄舟
黄舟オリジナル
2017-03-02 10:40:101606ブラウズ

前回の記事「Mybatisシリーズ徹底入門(2)---設定紹介(mybatisソースコード)」では、mybatisのソースコードを簡単に分析してみたところ、 mybatis設定ファイルでは、構成ルート ノードの下で、プロパティ、typeAliases、プラグイン、objectFactory、objectWrapperFactory、設定、環境、databaseIdProvider、typeHandlers、マッパーを構成できます。そこで今回は、まずプロパティノードと環境ノードを紹介します。

誰もが mybatis のソース コードを読みやすくするために、プロパティの使用方法の簡単な例を示します。

1 <configuration> 
2 <!-- 方法一: 从外部指定properties配置文件, 除了使用resource属性指定外,还可通过url属性指定url  
 3   <properties resource="dbConfig.properties"></properties> 
 4   --> 
 5   <!-- 方法二: 直接配置为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>


では、両方の方法を同時に使用した場合、どちらの方法が優先されるのでしょうか?

上記 2 つの方法を使用する場合、xml 設定が優先され、外部から指定されたプロパティ設定が 2 番目に優先されます。 その理由については、以下のソースコード解析に言及しますので、注目してください。

環境要素ノードの使用方法をもう一度見てみましょう:

b4577f0cc68e1344338606d41f433166
    bd8081f240c0ba1d02e7131e87b3e505
      82cb6174defe94ccb142b3939f5c338a
      9ecb1c9c1b287b7d311df838bbaa4cab
          1b6b568a3b45798dcde19eaa64f971c9
        f743351946f558b50f333d0624f47b74
        eb4ada9492c88878cd95167f36c0debf
        bd4c985c7b1dcc71e95f387f6cd38133         -->
         
         248f1a28c37521a6b0da1f654691e68d
         feae71514d1e227094cd56d4b60a5482
         c1d396130cce2b81003dd3101c07d62e
         698489c382eadc18214e1b3751dbb73a
         778a931854361d902df20b6736c4250d
         
      057950e86b81b87b31d408c1f841fee3
    1c6a0b0cba36824e074e3d9e369b2e45
    
    6887aa37263a59941cf4081a567eee07
    c2a8a650ad496d4441771c9ab92d5ed1
      82cb6174defe94ccb142b3939f5c338a
      9ecb1c9c1b287b7d311df838bbaa4cab
        0b920dbde3fcee7645488cd0606b4ac0
        5d60d8a690f2392b642287921ceaed1f
        160e534cf5ec65e0747697b8120a1e60
        eb4ada9492c88878cd95167f36c0debf
        bd4c985c7b1dcc71e95f387f6cd38133
      057950e86b81b87b31d408c1f841fee3
    1c6a0b0cba36824e074e3d9e369b2e45
    
  c7adc8b5a1b27fe5111bb8d60c6e2103


環境要素ノードは複数の環境サブノードで構成できます。

システムの開発環境と正式環境で使用されるデータベースが異なる場合 (これは間違いありません)、2 つの環境をセットアップできます。2 つの ID は開発環境 (dev) とたとえば、環境のデフォルト属性の値を dev に設定すると、dev の環境が選択されます。 これがどのように実装されるかについては、ソース コードについては後述します。

さて、上でプロパティと環境の設定を簡単に紹介しましたが、その後、正式にソース コードを見始めました:

前回、mybatis は XMLConfigBuilder クラスを通じて mybatis 設定ファイルを解析すると述べましたので、この記事は次へそれでは、XMLConfigBuilder のプロパティと環境の分析を見てみましょう:

XMLConfigBuilder:

  1 public class XMLConfigBuilder extends BaseBuilder {  
  2   
  3     private boolean parsed;  
  4     //xml解析器  
  5     private XPathParser parser;  
  6     private String environment;  
  7     
  8     //上次说到这个方法是在解析mybatis配置文件中能配置的元素节点  
  9     //今天首先要看的就是properties节点和environments节点 
  10     private void parseConfiguration(XNode root) { 
  11         try { 
  12           //解析properties元素 
  13           propertiesElement(root.evalNode("properties")); //issue #117 read properties first 
  14           typeAliasesElement(root.evalNode("typeAliases")); 
  15           pluginElement(root.evalNode("plugins")); 
  16           objectFactoryElement(root.evalNode("objectFactory")); 
  17           objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); 
  18           settingsElement(root.evalNode("settings")); 
  19           //解析environments元素 
  20           environmentsElement(root.evalNode("environments")); // read it after objectFactory and objectWrapperFactory issue #631 
  21           databaseIdProviderElement(root.evalNode("databaseIdProvider")); 
  22           typeHandlerElement(root.evalNode("typeHandlers")); 
  23           mapperElement(root.evalNode("mappers")); 
  24         } catch (Exception e) { 
  25           throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e); 
  26         } 
  27     } 
  28    
  29      
  30     //下面就看看解析properties的具体方法 
  31     private void propertiesElement(XNode context) throws Exception { 
  32         if (context != null) { 
  33           //将子节点的 name 以及value属性set进properties对象 
  34           //这儿可以注意一下顺序,xml配置优先, 外部指定properties配置其次 
  35           Properties defaults = context.getChildrenAsProperties(); 
  36           //获取properties节点上 resource属性的值 
  37           String resource = context.getStringAttribute("resource"); 
  38           //获取properties节点上 url属性的值, resource和url不能同时配置 
  39           String url = context.getStringAttribute("url"); 
  40           if (resource != null && url != null) { 
  41             throw new BuilderException("The properties element cannot specify both a URL and a resource based property file reference.  Please specify one or the other."); 
  42           } 
  43           //把解析出的properties文件set进Properties对象 
  44           if (resource != null) { 
  45             defaults.putAll(Resources.getResourceAsProperties(resource)); 
  46           } else if (url != null) { 
  47             defaults.putAll(Resources.getUrlAsProperties(url)); 
  48           } 
  49           //将configuration对象中已配置的Properties属性与刚刚解析的融合 
  50           //configuration这个对象会装载所解析mybatis配置文件的所有节点元素,以后也会频频提到这个对象 
  51           //既然configuration对象用有一系列的get/set方法, 那是否就标志着我们可以使用java代码直接配置? 
 52           //答案是肯定的, 不过使用配置文件进行配置,优势不言而喻 
 53           Properties vars = configuration.getVariables(); 
 54           if (vars != null) { 
 55             defaults.putAll(vars); 
 56           } 
 57           //把装有解析配置propertis对象set进解析器, 因为后面可能会用到 
 58           parser.setVariables(defaults); 
 59           //set进configuration对象 
 60           configuration.setVariables(defaults); 
 61         } 
 62     } 
 63      
 64     //下面再看看解析enviroments元素节点的方法 
 65     private void environmentsElement(XNode context) throws Exception { 
 66         if (context != null) { 
 67             if (environment == null) { 
 68                 //解析environments节点的default属性的值 
 69                 //例如: b4577f0cc68e1344338606d41f433166 
 70                 environment = context.getStringAttribute("default"); 
 71             } 
 72             //递归解析environments子节点 
 73             for (XNode child : context.getChildren()) { 
 74                 //bd8081f240c0ba1d02e7131e87b3e505, 只有enviroment节点有id属性,那么这个属性有何作用? 
 75                 //environments 节点下可以拥有多个 environment子节点 
 76                 //类似于这样: b4577f0cc68e1344338606d41f433166bd8081f240c0ba1d02e7131e87b3e505...1c6a0b0cba36824e074e3d9e369b2e45c2a8a650ad496d4441771c9ab92d5ed1...c7adc8b5a1b27fe5111bb8d60c6e2103 
 77                 //意思就是我们可以对应多个环境,比如开发环境,测试环境等, 由environments的default属性去选择对应的enviroment 
 78                 String id = child.getStringAttribute("id"); 
 79                 //isSpecial就是根据由environments的default属性去选择对应的enviroment 
 80                 if (isSpecifiedEnvironment(id)) { 
 81                     //事务, mybatis有两种:JDBC 和 MANAGED, 配置为JDBC则直接使用JDBC的事务,配置为MANAGED则是将事务托管给容器,  
 82                     TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager")); 
 83                     //enviroment节点下面就是dataSource节点了,解析dataSource节点(下面会贴出解析dataSource的具体方法) 
 84                     DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource")); 
 85                     DataSource dataSource = dsFactory.getDataSource(); 
 86                     Environment.Builder environmentBuilder = new Environment.Builder(id) 
 87                           .transactionFactory(txFactory) 
 88                           .dataSource(dataSource); 
 89                     //老规矩,会将dataSource设置进configuration对象 
 90                     configuration.setEnvironment(environmentBuilder.build()); 
 91                 } 
 92             } 
 93         } 
 94     } 
 95      
 96     //下面看看dataSource的解析方法 
 97     private DataSourceFactory dataSourceElement(XNode context) throws Exception { 
 98         if (context != null) { 
 99             //dataSource的连接池
 100             String type = context.getStringAttribute("type");
 101             //子节点 name, value属性set进一个properties对象
 102             Properties props = context.getChildrenAsProperties();
 103             //创建dataSourceFactory
 104             DataSourceFactory factory = (DataSourceFactory) resolveClass(type).newInstance();
 105             factory.setProperties(props);
 106             return factory;
 107         }
 108         throw new BuilderException("Environment declaration requires a DataSourceFactory.");
 109     } 
110 }


上記の mybatis ソース コードの解釈を通じて、誰もが mybatis の構成を深く理解できたと思います。

別の質問があります。上で見たように、${driver} という式は dataSource を構成するときに使用されました。このフォームはどのように解析されるのでしょうか。実際、これは PropertyParser クラスを通じて解析されます:

PropertyParser:

/**
 * 这个类解析${}这种形式的表达式 */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 + "}";
    }
  }
}


さて、上記はプロパティと環境要素ノードの分析であり、より重要なものはソース コードのコメントでマークされています。この記事はここで終了します。次の記事では引き続き他のノードの構成を分析します。

上記は、Mybatis シリーズ (3) - プロパティと環境の詳細な設定 (mybatis ソース コード) の内容です。その他の関連コンテンツについては、PHP 中国語 Web サイト (www.php.cn) に注目してください。



声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。