Mybaits源码分析六之XMLConfigBuilder类 environments标签解析

根据mybatis配置加载流程 

 1 private void parseConfiguration(XNode root) {
 2     try {
 3       //解析子节点的properties文件
 4       propertiesElement(root.evalNode("properties"));
 5       //加载用户自定义配置
 6       Properties settings = settingsAsProperties(root.evalNode("settings"));
 7       //加载vfs虚拟文件系统配置
 8       loadCustomVfs(settings);
 9      // 解析子节点typeAliases 别名
10       typeAliasesElement(root.evalNode("typeAliases"));
11       //解析子节点plugins 插件
12       pluginElement(root.evalNode("plugins"));
13       //解析子节点objectFactory mybatis为结果创建对象时都会用到objectFactory
14       objectFactoryElement(root.evalNode("objectFactory"));
15       //解析子节点的封装对象
16       objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
17       reflectorFactoryElement(root.evalNode("reflectorFactory"));
18       //解析settings标签的文件配置
19       settingsElement(settings);
20       //配置运行环境
21       environmentsElement(root.evalNode("environments"));
22       //解析子节点配置数据库供应商
23       databaseIdProviderElement(root.evalNode("databaseIdProvider"));
24       //解析对象类型处理器,处理Java的pojo类型与数据库类型的映射
25       typeHandlerElement(root.evalNode("typeHandlers"));
26       //解析子节点的mappers
27       mapperElement(root.evalNode("mappers"));
28     } catch (Exception e) {
29       throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
30     }
31   }
environmentsElement(root.evalNode("environments"));主要处理连接数据库配置,在mybatis配置文件中的写法为:
 1 <!--默认为development 环境,通过此配置会寻找 >-->
 2 <environments default="development">
 3        <!--当前运行环境-->
 4         <environment id="development">
 5           <!--指定任务管理器-->
 6             <transactionManager type="JDBC"/>
 7           <!--指定数据源-->
 8             <dataSource type="POOLED">
 9                 <property name="driver" value="${jdbc.driver}"/>
10                 <property name="url" value="${jdbc.url}"/>
11                 <property name="username" value="${jdbc.username}"/>
12                 <property name="password" value="${jdbc.password}"/>
13             </dataSource>
14         </environment>
15     </environments>
任务管理器 <transactionManager type="JDBC"/>中type属性有两个值分别是 JDBC,MANAGED。type也可以自定义实现事务管理
JDBC是指 JdbcTransactionFactory 生成的 JdbcTransaction 对象实现。它是以 JDBC 的方式对数据库的提交和回滚进行操作
MANAGED 使用 ManagedTransactionFactory 生成的 ManagedTransaction 对象实现。它的提交和回滚方法不用任何操作,而是把事务交给容器处理。在默认情况下,它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。
数据源配置形式 <dataSource type="POOLED"> 中type的属性值分别为JNDI,POOLED,UNPOOLED
UNPOOLED 采用非数据库池的管理方式,每次请求都会打开一个新的数据库连接,所以创建会比较慢。基于UnpooledDataSourceFactory实现
POOLED数据源 POOLED 利用“池”的概念将 JDBC 的 Connection 对象组织起来,它开始会有一些空置,并且已经连接好的数据库连接,所以请求时,无须再建立和验证,省去了创建新的连接实例时所必需的初始化和认证时间。它还控制最大连接数,避免过多的连接导致系统瓶颈。是基于PooledDataSourceFactory实现
JNDI数据源 JNDI 的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。是基于JndiDataSourceFactory实现
environmentsElement方法为:
 1   private void environmentsElement(XNode context) throws Exception {
 2     if (context != null) {
 3       if (environment == null) {
 4         environment = context.getStringAttribute("default");
 5       }
 6       for (XNode child : context.getChildren()) {
 7       //获取environment配置ID值
 8         String id = child.getStringAttribute("id");
 9     //判断指定的环境ID与各子节点的环境ID是否一致
10         if (isSpecifiedEnvironment(id)) {
11       //加载事务管理器
12           TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
13       //加载数据源
14           DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
15           DataSource dataSource = dsFactory.getDataSource();
16           Environment.Builder environmentBuilder = new Environment.Builder(id)
17               .transactionFactory(txFactory)
18               .dataSource(dataSource);
19           configuration.setEnvironment(environmentBuilder.build());
20         }
21       }
22     }
23   }
isSpecifiedEnvironment(id)方法为:
 1  private boolean isSpecifiedEnvironment(String id) {
 2     if (environment == null) {
 3       throw new BuilderException("No environment specified.");
 4     } else if (id == null) {
 5       throw new BuilderException("Environment requires an id attribute.");
 6     } else if (environment.equals(id)) {
 7       return true;
 8     }
 9     return false;
10   }
transactionManagerElement方法为
 1 private TransactionFactory transactionManagerElement(XNode context) throws Exception {
 2     if (context != null) {
 3       String type = context.getStringAttribute("type");
 4    //获取子节点
 5       Properties props = context.getChildrenAsProperties();
 6    //根据type参数获取事务管理器实例
 7       TransactionFactory factory = (TransactionFactory) resolveClass(type).newInstance();
 8       factory.setProperties(props);
 9       return factory;
10     }
dataSourceElement数据源加载
 1 private DataSourceFactory dataSourceElement(XNode context) throws Exception {
 2     if (context != null) {
 3       String type = context.getStringAttribute("type");
 4       Properties props = context.getChildrenAsProperties();
 5       DataSourceFactory factory = (DataSourceFactory) resolveClass(type).newInstance();
 6       factory.setProperties(props);
 7       return factory;
 8     }
 9     throw new BuilderException("Environment declaration requires a DataSourceFactory.");
10   }