首页 > 代码库 > Mybatis的Environment解析详解

Mybatis的Environment解析详解

今天来具体看一下如何解析environments 
//XMLConfigBuilder 

Java代码  技术分享

  1. private void parseConfiguration(XNode root)  

  2.     {  

  3.         try  

  4.         {  

  5.             propertiesElement(root.evalNode("properties"));  

  6.             typeAliasesElement(root.evalNode("typeAliases"));  

  7.             pluginElement(root.evalNode("plugins"));  

  8.             objectFactoryElement(root.evalNode("objectFactory"));  

  9.             objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));  

  10.             settingsElement(root.evalNode("settings"));  

  11.         //解析environments  

  12.             environmentsElement(root.evalNode("environments"));  

  13.             databaseIdProviderElement(root.evalNode("databaseIdProvider"));  

  14.             typeHandlerElement(root.evalNode("typeHandlers"));  

  15.             mapperElement(root.evalNode("mappers"));  

  16.         }  

  17.         catch(Exception e)  

  18.         {  

  19.             throw new BuilderException((new StringBuilder()).append("Error parsing SQL Mapper Configuration. Cause: ").append(e).toString(), e);  

  20.         }  

  21.     }  

  22. //解析environments  

  23. private void environmentsElement(XNode context)  

  24.         throws Exception  

  25.     {  

  26.         if(context != null)  

  27.         {  

  28.             if(C == null)  

  29.                 environment = context.getStringAttribute("default");  

  30.             Iterator i$ = context.getChildren().iterator();  

  31.         //遍历environments的child节点environment,并解析  

  32.             do  

  33.             {  

  34.                 if(!i$.hasNext())  

  35.                     break;  

  36.                 XNode child = (XNode)i$.next();  

  37.                 String id = child.getStringAttribute("id");  

  38.         //如果environment的id属性,与environments的default相同时,才解析  

  39.                 if(isSpecifiedEnvironment(id))  

  40.                 {  

  41.             //解析transactionManager  

  42.                     TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));  

  43.                     //解析dataSource  

  44.             DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));  

  45.                     javax.sql.DataSource dataSource = dsFactory.getDataSource();  

  46.                     org.apache.ibatis.mapping.Environment.Builder environmentBuilder = (new org.apache.ibatis.mapping.Environment.Builder(id)).transactionFactory(txFactory).dataSource(dataSource);  

  47.                     configuration.setEnvironment(environmentBuilder.build());  

  48.                 }  

  49.             } while(true);  

  50.         }  

  51.     }  


//解析transactionManager 
先看configuration的构造,启动有JDBC,POOLED类型的映射关系,这个在解析environment节点时,需要用到下载 

Java代码  技术分享

  1. typeAliasRegistry.registerAlias("JDBC", org/apache/ibatis/transaction/jdbc/JdbcTransactionFactory);  

  2. typeAliasRegistry.registerAlias("POOLED", org/apache/ibatis/datasource/pooled/PooledDataSourceFactory);  



Java代码  技术分享

  1. public Configuration()  

  2.     {  

  3.         safeRowBoundsEnabled = false;  

  4.         safeResultHandlerEnabled = true;  

  5.         mapUnderscoreToCamelCase = false;  

  6.         aggressiveLazyLoading = true;  

  7.         multipleResultSetsEnabled = true;  

  8.         useGeneratedKeys = false;//允许JDBC支持生成的键  

  9.         useColumnLabel = true;  

  10.         cacheEnabled = true;//全局的映射器启用或禁用缓存  

  11.         callSettersOnNulls = false;  

  12.         localCacheScope = LocalCacheScope.SESSION;//本地一级缓存作用域  

  13.         jdbcTypeForNull = JdbcType.OTHER;  

  14.         lazyLoadTriggerMethods = new HashSet(Arrays.asList(new String[] {  

  15.             "equals""clone""hashCode""toString"  

  16.         }));  

  17.         defaultExecutorType = ExecutorType.SIMPLE;  

  18.         autoMappingBehavior = AutoMappingBehavior.PARTIAL;  

  19.         variables = new Properties();  

  20.         objectFactory = new DefaultObjectFactory();//默认ObjectFactory  

  21.         objectWrapperFactory = new DefaultObjectWrapperFactory();//默认DefaultObjectWrapperFactory  

  22.         mapperRegistry = new MapperRegistry(this);  

  23.         lazyLoadingEnabled = false;  

  24.         interceptorChain = new InterceptorChain();//插件链  

  25.         typeHandlerRegistry = new TypeHandlerRegistry();//类型处理注册器  

  26.         typeAliasRegistry = new TypeAliasRegistry();//类型别名注册器  

  27.         languageRegistry = new LanguageDriverRegistry();  

  28.     //mappedStatements Map  

  29.         mappedStatements = new StrictMap("Mapped Statements collection");  

  30.     //mappedStatements,method,二级缓存  

  31.         caches = new StrictMap("Caches collection");  

  32.     //MapperInterface 方法返回结果类型Map  

  33.         resultMaps = new StrictMap("Result Maps collection");  

  34.         //MapperInterface 方法参数类型Map  

  35.         parameterMaps = new StrictMap("Parameter Maps collection");  

  36.     //主键生成器Map  

  37.         keyGenerators = new StrictMap("Key Generators collection");  

  38.         loadedResources = new HashSet();  

  39.     //Mapper.xml 中statement片段  

  40.         sqlFragments = new StrictMap("XML fragments parsed from previous mappers");  

  41.     //未解析处理的statements  

  42.         incompleteStatements = new LinkedList();  

  43.     //未解析处理的CacheRefs  

  44.         incompleteCacheRefs = new LinkedList();  

  45.     //未解析处理的ResultMaps  

  46.         incompleteResultMaps = new LinkedList();  

  47.     //未解析处理的Methods  

  48.         incompleteMethods = new LinkedList();  

  49.         cacheRefMap = new HashMap();  

  50.         typeAliasRegistry.registerAlias("JDBC", org/apache/ibatis/transaction/jdbc/JdbcTransactionFactory);  

  51.         typeAliasRegistry.registerAlias("MANAGED", org/apache/ibatis/transaction/managed/ManagedTransactionFactory);  

  52.         typeAliasRegistry.registerAlias("JNDI", org/apache/ibatis/datasource/jndi/JndiDataSourceFactory);  

  53.         typeAliasRegistry.registerAlias("POOLED", org/apache/ibatis/datasource/pooled/PooledDataSourceFactory);  

  54.         typeAliasRegistry.registerAlias("UNPOOLED", org/apache/ibatis/datasource/unpooled/UnpooledDataSourceFactory);  

  55.         typeAliasRegistry.registerAlias("PERPETUAL", org/apache/ibatis/cache/impl/PerpetualCache);  

  56.         typeAliasRegistry.registerAlias("FIFO", org/apache/ibatis/cache/decorators/FifoCache);  

  57.         typeAliasRegistry.registerAlias("LRU", org/apache/ibatis/cache/decorators/LruCache);  

  58.         typeAliasRegistry.registerAlias("SOFT", org/apache/ibatis/cache/decorators/SoftCache);  

  59.         typeAliasRegistry.registerAlias("WEAK", org/apache/ibatis/cache/decorators/WeakCache);  

  60.         typeAliasRegistry.registerAlias("VENDOR", org/apache/ibatis/mapping/VendorDatabaseIdProvider);  

  61.         typeAliasRegistry.registerAlias("XML", org/apache/ibatis/scripting/xmltags/XMLLanguageDriver);  

  62.         typeAliasRegistry.registerAlias("RAW", org/apache/ibatis/scripting/defaults/RawLanguageDriver);  

  63.         typeAliasRegistry.registerAlias("SLF4J", org/apache/ibatis/logging/slf4j/Slf4jImpl);  

  64.         typeAliasRegistry.registerAlias("COMMONS_LOGGING", org/apache/ibatis/logging/commons/JakartaCommonsLoggingImpl);  

  65.         typeAliasRegistry.registerAlias("LOG4J", org/apache/ibatis/logging/log4j/Log4jImpl);  

  66.         typeAliasRegistry.registerAlias("JDK_LOGGING", org/apache/ibatis/logging/jdk14/Jdk14LoggingImpl);  

  67.         typeAliasRegistry.registerAlias("STDOUT_LOGGING", org/apache/ibatis/logging/stdout/StdOutImpl);  

  68.         typeAliasRegistry.registerAlias("NO_LOGGING", org/apache/ibatis/logging/nologging/NoLoggingImpl);  

  69.         typeAliasRegistry.registerAlias("CGLIB", org/apache/ibatis/executor/loader/CglibProxyFactory);  

  70.         typeAliasRegistry.registerAlias("JAVASSIST", org/apache/ibatis/executor/loader/JavassistProxyFactory);  

  71.         languageRegistry.setDefaultDriverClass(org/apache/ibatis/scripting/xmltags/XMLLanguageDriver);  

  72.         languageRegistry.register(org/apache/ibatis/scripting/defaults/RawLanguageDriver);  

  73.     }  


从上可以看出JDBC,POOLED类型别名的映射关系如下: 
JDBC,JdbcTransactionFactory 下载
POOLED,PooledDataSourceFactory 


Java代码  技术分享

  1. <environments default="development">  

  2.         <environment id="development">  

  3.             <transactionManager type="JDBC" />  

  4.             <dataSource type="POOLED">  

  5.                 <property name="driver" value=http://www.mamicode.com/"${driver}" />  

  6.                 <property name="url" value=http://www.mamicode.com/"${url}" />  

  7.                 <property name="username" value=http://www.mamicode.com/"${username}" />  

  8.                 <property name="password" value=http://www.mamicode.com/"${password}" />  

  9.             </dataSource>  

  10.         </environment>  

  11. </environments>  



Java代码  技术分享

  1. private TransactionFactory transactionManagerElement(XNode context)  

  2.         throws Exception  

  3.     {  

  4.         if(context != null)  

  5.         {  

  6.             String type = context.getStringAttribute("type");  

  7.             Properties props = context.getChildrenAsProperties();  

  8.         //从类型解决器中,获取type对应的类型的实例,从上面的配置来看  

  9.         //实际为JdbcTransactionFactory  

  10.             TransactionFactory factory = (TransactionFactory)resolveClass(type).newInstance();  

  11.         //设置JdbcTransactionFactory属性  

  12.             factory.setProperties(props);  

  13.             return factory;  

  14.         } else  

  15.         {  

  16.             throw new BuilderException("Environment declaration requires a TransactionFactory.");  

  17.         }  

  18.     }  



//JdbcTransactionFactory 

Java代码  下载

  1. public class JdbcTransactionFactory  

  2.     implements TransactionFactory  

  3. {  

  4.     public void setProperties(Properties properties)  

  5.     {  

  6.     }  

  7.    //根据数据连接新建事务  

  8.     public Transaction newTransaction(Connection conn)  

  9.     {  

  10.         return new JdbcTransaction(conn);  

  11.     }  

  12.     //根据数据源和事务级别和是否自动提交,新建事务  

  13.     public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit)  

  14.     {  

  15.         return new JdbcTransaction(ds, level, autoCommit);  

  16.     }  

  17. }  



//TransactionFactory 

Java代码  技术分享

  1. public interface TransactionFactory  

  2. {  

  3.     public abstract void setProperties(Properties properties);  

  4.     public abstract Transaction newTransaction(Connection connection);  

  5.     public abstract Transaction newTransaction(DataSource datasource, TransactionIsolationLevel transactionisolationlevel, boolean flag);  

  6. }  


现在来看一下jdbc事务 

Java代码  下载

  1. public class JdbcTransaction  

  2.     implements Transaction  

  3. {  

  4.     private static final Log log = LogFactory.getLog(org/apache/ibatis/transaction/jdbc/JdbcTransaction);  

  5.     protected Connection connection;//数据库连接  

  6.     protected DataSource dataSource;//数据源  

  7.     protected TransactionIsolationLevel level;//事务级别  

  8.     protected boolean autoCommmit;//自动提交属性  

  9.   

  10.     public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit)  

  11.     {  

  12.         dataSource = ds;  

  13.         level = desiredLevel;  

  14.         autoCommmit = desiredAutoCommit;  

  15.     }  

  16.   

  17.     public JdbcTransaction(Connection connection)  

  18.     {  

  19.         this.connection = connection;  

  20.     }  

  21.   

  22.     public Connection getConnection()  

  23.         throws SQLException  

  24.     {  

  25.         if(connection == null)  

  26.             openConnection();  

  27.         return connection;  

  28.     }  

  29.   

  30.     public void commit()  

  31.         throws SQLException  

  32.     {  

  33.         if(connection != null && !connection.getAutoCommit())  

  34.         {  

  35.             if(log.isDebugEnabled())  

  36.                 log.debug((new StringBuilder()).append("Committing JDBC Connection [").append(connection).append("]").toString());  

  37.             connection.commit();  

  38.         }  

  39.     }  

  40.   

  41.     public void rollback()  

  42.         throws SQLException  

  43.     {  

  44.         if(connection != null && !connection.getAutoCommit())  

  45.         {  

  46.             if(log.isDebugEnabled())  

  47.                 log.debug((new StringBuilder()).append("Rolling back JDBC Connection [").append(connection).append("]").toString());  

  48.             connection.rollback();  

  49.         }  

  50.     }  

  51.   

  52.     public void close()  

  53.         throws SQLException  

  54.     {  

  55.         if(connection != null)  

  56.         {  

  57.             resetAutoCommit();  

  58.             if(log.isDebugEnabled())  

  59.                 log.debug((new StringBuilder()).append("Closing JDBC Connection [").append(connection).append("]").toString());  

  60.             connection.close();  

  61.         }  

  62.     }  

  63.   

  64.     protected void setDesiredAutoCommit(boolean desiredAutoCommit)  

  65.     {  

  66.         try  

  67.         {  

  68.             if(connection.getAutoCommit() != desiredAutoCommit)  

  69.             {  

  70.                 if(log.isDebugEnabled())  

  71.                     log.debug((new StringBuilder()).append("Setting autocommit to ").append(desiredAutoCommit).append(" on JDBC Connection [").append(connection).append("]").toString());  

  72.                 connection.setAutoCommit(desiredAutoCommit);  

  73.             }  

  74.         }  

  75.         catch(SQLException e)  

  76.         {  

  77.             throw new TransactionException((new StringBuilder()).append("Error configuring AutoCommit.  Your driver may not support getAutoCommit() or setAutoCommit(). Requested setting: ").append(desiredAutoCommit).append(".  Cause: ").append(e).toString(), e);  

  78.         }  

  79.     }  

  80.   

  81.     protected void resetAutoCommit()  

  82.     {  

  83.         try  

  84.         {  

  85.             if(!connection.getAutoCommit())  

  86.             {  

  87.                 if(log.isDebugEnabled())  

  88.                     log.debug((new StringBuilder()).append("Resetting autocommit to true on JDBC Connection [").append(connection).append("]").toString());  

  89.                 connection.setAutoCommit(true);  

  90.             }  

  91.         }  

  92.         catch(SQLException e)  

  93.         {  

  94.             log.debug((new StringBuilder()).append("Error resetting autocommit to true before closing the connection.  Cause: ").append(e).toString());  

  95.         }  

  96.     }  

  97.     //获取connection  

  98.     protected void openConnection()  

  99.         throws SQLException  

  100.     {  

  101.         if(log.isDebugEnabled())  

  102.             log.debug("Openning JDBC Connection");  

  103.         connection = dataSource.getConnection();  

  104.         if(level != null)  

  105.             connection.setTransactionIsolation(level.getLevel());  

  106.         setDesiredAutoCommit(autoCommmit);  

  107.     }  

  108. }  


//Transaction 

Java代码  技术分享

  1. public interface Transaction  

  2. {  

  3.   

  4.     public abstract Connection getConnection()  

  5.         throws SQLException;  

  6.   

  7.     public abstract void commit()  

  8.         throws SQLException;  

  9.   

  10.     public abstract void rollback()  

  11.         throws SQLException;  

  12.   

  13.     public abstract void close()  

  14.         throws SQLException;  

  15. }  


从上面可以看出jdbc对应的事务工厂为JdbcTransactionFactory,由JdbcTransactionFactory,根据数据源,事务级别以及自动提交属性来,创建JdbcTransaction,而JdbcTransaction的事务管理,是通过数据连接connection,而connection是从datasource获取,JdbcTransaction的事务管理,就是依靠相应的数据库driver,来管理,实际依赖于数据库。 下载

//解析dataSource 

Java代码  技术分享

  1. private DataSourceFactory dataSourceElement(XNode context)  

  2.         throws Exception  

  3.     {  

  4.         if(context != null)  

  5.         {  

  6.         //获取数据源的类型,和属性  

  7.             String type = context.getStringAttribute("type");  

  8.             Properties props = context.getChildrenAsProperties();  

  9.         //根据type从configuration的类型处理器,获取具体的DataSourceFactory  

  10.         //从上文,我们看一看到type为POOLED,对应的是PooledDataSourceFactory  

  11.             DataSourceFactory factory = (DataSourceFactory)resolveClass(type).newInstance();  

  12.             factory.setProperties(props);  

  13.             return factory;  

  14.         } else  

  15.         {  

  16.             throw new BuilderException("Environment declaration requires a DataSourceFactory.");  

  17.         }  

  18.     }  


// PooledDataSourceFactory 

Java代码  技术分享

  1. public class PooledDataSourceFactory extends UnpooledDataSourceFactory  

  2. {  

  3.   

  4.     public PooledDataSourceFactory()  

  5.     {  

  6.         dataSource = new PooledDataSource();  

  7.     }  

  8. }  


Mybatis的Environment解析详解