根据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 环境,通过此配置会寻找 id="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 }