Mybatis的Environment解析详解

SqlSessionFactory初始化:[url]http://donald-draper.iteye.com/blog/2331917[/url]
Mybatis加载解析Mapper(xml)文件第一讲:[url]http://donald-draper.iteye.com/blog/2333125[/url]
Mybatis加载解析Mapper(xml)文件第二讲:[url]http://donald-draper.iteye.com/blog/2333191[/url]
Mybatis 解析Mapper(class):[url]http://donald-draper.iteye.com/blog/2333293[/url]
//全局文件的解析的方法在XMLConfigBuilder中,今天来具体看一下如何解析environments
//XMLConfigBuilder
private void parseConfiguration(XNode root)
{
try
{
propertiesElement(root.evalNode("properties"));
typeAliasesElement(root.evalNode("typeAliases"));
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
settingsElement(root.evalNode("settings"));
//解析environments
environmentsElement(root.evalNode("environments"));
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
typeHandlerElement(root.evalNode("typeHandlers"));
mapperElement(root.evalNode("mappers"));
}
catch(Exception e)
{
throw new BuilderException((new StringBuilder()).append("Error parsing SQL Mapper Configuration. Cause: ").append(e).toString(), e);
}
}
//解析environments
private void environmentsElement(XNode context)
throws Exception
{
if(context != null)
{
if(C == null)
environment = context.getStringAttribute("default");
Iterator i$ = context.getChildren().iterator();
//遍历environments的child节点environment,并解析
do
{
if(!i$.hasNext())
break;
XNode child = (XNode)i$.next();
String id = child.getStringAttribute("id");
//如果environment的id属性,与environments的default相同时,才解析
if(isSpecifiedEnvironment(id))
{
//解析transactionManager
TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
//解析dataSource
DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
javax.sql.DataSource dataSource = dsFactory.getDataSource();
org.apache.ibatis.mapping.Environment.Builder environmentBuilder = (new org.apache.ibatis.mapping.Environment.Builder(id)).transactionFactory(txFactory).dataSource(dataSource);
configuration.setEnvironment(environmentBuilder.build());
}
} while(true);
}
}

//解析transactionManager
先看configuration的构造,启动有JDBC,POOLED类型的映射关系,这个在解析environment节点时,需要用到
typeAliasRegistry.registerAlias("JDBC", org/apache/ibatis/transaction/jdbc/JdbcTransactionFactory);
typeAliasRegistry.registerAlias("POOLED", org/apache/ibatis/datasource/pooled/PooledDataSourceFactory);


public Configuration()
{
safeRowBoundsEnabled = false;
safeResultHandlerEnabled = true;
mapUnderscoreToCamelCase = false;
aggressiveLazyLoading = true;
multipleResultSetsEnabled = true;
useGeneratedKeys = false;//允许JDBC支持生成的键
useColumnLabel = true;
cacheEnabled = true;//全局的映射器启用或禁用缓存
callSettersOnNulls = false;
localCacheScope = LocalCacheScope.SESSION;//本地一级缓存作用域
jdbcTypeForNull = JdbcType.OTHER;
lazyLoadTriggerMethods = new HashSet(Arrays.asList(new String[] {
"equals", "clone", "hashCode", "toString"
}));
defaultExecutorType = ExecutorType.SIMPLE;
autoMappingBehavior = AutoMappingBehavior.PARTIAL;
variables = new Properties();
objectFactory = new DefaultObjectFactory();//默认ObjectFactory
objectWrapperFactory = new DefaultObjectWrapperFactory();//默认DefaultObjectWrapperFactory
mapperRegistry = new MapperRegistry(this);
lazyLoadingEnabled = false;
interceptorChain = new InterceptorChain();//插件链
typeHandlerRegistry = new TypeHandlerRegistry();//类型处理注册器
typeAliasRegistry = new TypeAliasRegistry();//类型别名注册器
languageRegistry = new LanguageDriverRegistry();
//mappedStatements Map
mappedStatements = new StrictMap("Mapped Statements collection");
//mappedStatements,method,二级缓存
caches = new StrictMap("Caches collection");
//MapperInterface 方法返回结果类型Map
resultMaps = new StrictMap("Result Maps collection");
//MapperInterface 方法参数类型Map
parameterMaps = new StrictMap("Parameter Maps collection");
//主键生成器Map
keyGenerators = new StrictMap("Key Generators collection");
loadedResources = new HashSet();
//Mapper.xml 中statement片段
sqlFragments = new StrictMap("XML fragments parsed from previous mappers");
//未解析处理的statements
incompleteStatements = new LinkedList();
//未解析处理的CacheRefs
incompleteCacheRefs = new LinkedList();
//未解析处理的ResultMaps
incompleteResultMaps = new LinkedList();
//未解析处理的Methods
incompleteMethods = new LinkedList();
cacheRefMap = new HashMap();
typeAliasRegistry.registerAlias("JDBC", org/apache/ibatis/transaction/jdbc/JdbcTransactionFactory);
typeAliasRegistry.registerAlias("MANAGED", org/apache/ibatis/transaction/managed/ManagedTransactionFactory);
typeAliasRegistry.registerAlias("JNDI", org/apache/ibatis/datasource/jndi/JndiDataSourceFactory);
typeAliasRegistry.registerAlias("POOLED", org/apache/ibatis/datasource/pooled/PooledDataSourceFactory);
typeAliasRegistry.registerAlias("UNPOOLED", org/apache/ibatis/datasource/unpooled/UnpooledDataSourceFactory);
typeAliasRegistry.registerAlias("PERPETUAL", org/apache/ibatis/cache/impl/PerpetualCache);
typeAliasRegistry.registerAlias("FIFO", org/apache/ibatis/cache/decorators/FifoCache);
typeAliasRegistry.registerAlias("LRU", org/apache/ibatis/cache/decorators/LruCache);
typeAliasRegistry.registerAlias("SOFT", org/apache/ibatis/cache/decorators/SoftCache);
typeAliasRegistry.registerAlias("WEAK", org/apache/ibatis/cache/decorators/WeakCache);
typeAliasRegistry.registerAlias("VENDOR", org/apache/ibatis/mapping/VendorDatabaseIdProvider);
typeAliasRegistry.registerAlias("XML", org/apache/ibatis/scripting/xmltags/XMLLanguageDriver);
typeAliasRegistry.registerAlias("RAW", org/apache/ibatis/scripting/defaults/RawLanguageDriver);
typeAliasRegistry.registerAlias("SLF4J", org/apache/ibatis/logging/slf4j/Slf4jImpl);
typeAliasRegistry.registerAlias("COMMONS_LOGGING", org/apache/ibatis/logging/commons/JakartaCommonsLoggingImpl);
typeAliasRegistry.registerAlias("LOG4J", org/apache/ibatis/logging/log4j/Log4jImpl);
typeAliasRegistry.registerAlias("JDK_LOGGING", org/apache/ibatis/logging/jdk14/Jdk14LoggingImpl);
typeAliasRegistry.registerAlias("STDOUT_LOGGING", org/apache/ibatis/logging/stdout/StdOutImpl);
typeAliasRegistry.registerAlias("NO_LOGGING", org/apache/ibatis/logging/nologging/NoLoggingImpl);
typeAliasRegistry.registerAlias("CGLIB", org/apache/ibatis/executor/loader/CglibProxyFactory);
typeAliasRegistry.registerAlias("JAVASSIST", org/apache/ibatis/executor/loader/JavassistProxyFactory);
languageRegistry.setDefaultDriverClass(org/apache/ibatis/scripting/xmltags/XMLLanguageDriver);
languageRegistry.register(org/apache/ibatis/scripting/defaults/RawLanguageDriver);
}

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


<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>


private TransactionFactory transactionManagerElement(XNode context)
throws Exception
{
if(context != null)
{
String type = context.getStringAttribute("type");
Properties props = context.getChildrenAsProperties();
//从类型解决器中,获取type对应的类型的实例,从上面的配置来看
//实际为JdbcTransactionFactory
TransactionFactory factory = (TransactionFactory)resolveClass(type).newInstance();
//设置JdbcTransactionFactory属性
factory.setProperties(props);
return factory;
} else
{
throw new BuilderException("Environment declaration requires a TransactionFactory.");
}
}


//JdbcTransactionFactory
public class JdbcTransactionFactory
implements TransactionFactory
{
public void setProperties(Properties properties)
{
}
//根据数据连接新建事务
public Transaction newTransaction(Connection conn)
{
return new JdbcTransaction(conn);
}
//根据数据源和事务级别和是否自动提交,新建事务
public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit)
{
return new JdbcTransaction(ds, level, autoCommit);
}
}


//TransactionFactory
public interface TransactionFactory
{
public abstract void setProperties(Properties properties);
public abstract Transaction newTransaction(Connection connection);
public abstract Transaction newTransaction(DataSource datasource, TransactionIsolationLevel transactionisolationlevel, boolean flag);
}

现在来看一下jdbc事务

public class JdbcTransaction
implements Transaction
{
private static final Log log = LogFactory.getLog(org/apache/ibatis/transaction/jdbc/JdbcTransaction);
protected Connection connection;//数据库连接
protected DataSource dataSource;//数据源
protected TransactionIsolationLevel level;//事务级别
protected boolean autoCommmit;//自动提交属性

public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit)
{
dataSource = ds;
level = desiredLevel;
autoCommmit = desiredAutoCommit;
}

public JdbcTransaction(Connection connection)
{
this.connection = connection;
}

public Connection getConnection()
throws SQLException
{
if(connection == null)
openConnection();
return connection;
}

public void commit()
throws SQLException
{
if(connection != null && !connection.getAutoCommit())
{
if(log.isDebugEnabled())
log.debug((new StringBuilder()).append("Committing JDBC Connection [").append(connection).append("]").toString());
connection.commit();
}
}

public void rollback()
throws SQLException
{
if(connection != null && !connection.getAutoCommit())
{
if(log.isDebugEnabled())
log.debug((new StringBuilder()).append("Rolling back JDBC Connection [").append(connection).append("]").toString());
connection.rollback();
}
}

public void close()
throws SQLException
{
if(connection != null)
{
resetAutoCommit();
if(log.isDebugEnabled())
log.debug((new StringBuilder()).append("Closing JDBC Connection [").append(connection).append("]").toString());
connection.close();
}
}

protected void setDesiredAutoCommit(boolean desiredAutoCommit)
{
try
{
if(connection.getAutoCommit() != desiredAutoCommit)
{
if(log.isDebugEnabled())
log.debug((new StringBuilder()).append("Setting autocommit to ").append(desiredAutoCommit).append(" on JDBC Connection [").append(connection).append("]").toString());
connection.setAutoCommit(desiredAutoCommit);
}
}
catch(SQLException e)
{
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);
}
}

protected void resetAutoCommit()
{
try
{
if(!connection.getAutoCommit())
{
if(log.isDebugEnabled())
log.debug((new StringBuilder()).append("Resetting autocommit to true on JDBC Connection [").append(connection).append("]").toString());
connection.setAutoCommit(true);
}
}
catch(SQLException e)
{
log.debug((new StringBuilder()).append("Error resetting autocommit to true before closing the connection. Cause: ").append(e).toString());
}
}
//获取connection
protected void openConnection()
throws SQLException
{
if(log.isDebugEnabled())
log.debug("Openning JDBC Connection");
connection = dataSource.getConnection();
if(level != null)
connection.setTransactionIsolation(level.getLevel());
setDesiredAutoCommit(autoCommmit);
}
}


//Transaction
public interface Transaction
{

public abstract Connection getConnection()
throws SQLException;

public abstract void commit()
throws SQLException;

public abstract void rollback()
throws SQLException;

public abstract void close()
throws SQLException;
}

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

//解析dataSource
private DataSourceFactory dataSourceElement(XNode context)
throws Exception
{
if(context != null)
{
//获取数据源的类型,和属性
String type = context.getStringAttribute("type");
Properties props = context.getChildrenAsProperties();
//根据type从configuration的类型处理器,获取具体的DataSourceFactory
//从上文,我们看一看到type为POOLED,对应的是PooledDataSourceFactory
DataSourceFactory factory = (DataSourceFactory)resolveClass(type).newInstance();
factory.setProperties(props);
return factory;
} else
{
throw new BuilderException("Environment declaration requires a DataSourceFactory.");
}
}

// PooledDataSourceFactory
public class PooledDataSourceFactory extends UnpooledDataSourceFactory
{

public PooledDataSourceFactory()
{
dataSource = new PooledDataSource();
}
}


//UnpooledDataSourceFactory
public class UnpooledDataSourceFactory
implements DataSourceFactory
{
private static final String DRIVER_PROPERTY_PREFIX = "driver.";
private static final int DRIVER_PROPERTY_PREFIX_LENGTH = "driver.".length();
protected DataSource dataSource;

public UnpooledDataSourceFactory()
{
dataSource = new UnpooledDataSource();
}

public void setProperties(Properties properties)
{
Properties driverProperties = new Properties();
//获取dataSource的对象描述
MetaObject metaDataSource = SystemMetaObject.forObject(dataSource);
//获取dataSource的所有属性,并设置
for(Iterator i$ = properties.keySet().iterator(); i$.hasNext();)
{
Object key = i$.next();
String propertyName = (String)key;
if(propertyName.startsWith("driver."))
{
String value = properties.getProperty(propertyName);
driverProperties.setProperty(propertyName.substring(DRIVER_PROPERTY_PREFIX_LENGTH), value);
} else
if(metaDataSource.hasSetter(propertyName))
{
String value = (String)properties.get(propertyName);
Object convertedValue = convertValue(metaDataSource, propertyName, value);
metaDataSource.setValue(propertyName, convertedValue);
} else
{
throw new DataSourceException((new StringBuilder()).append("Unknown DataSource property: ").append(propertyName).toString());
}
}
//设置metaDataSource的driverProperties属性
if(driverProperties.size() > 0)
metaDataSource.setValue("driverProperties", driverProperties);
}

public DataSource getDataSource()
{
return dataSource;
}
//将value转化为metaDataSource的对应setValue的参数类型
private Object convertValue(MetaObject metaDataSource, String propertyName, String value)
{
Object convertedValue = value;
Class targetType = metaDataSource.getSetterType(propertyName);
if(targetType == java/lang/Integer || targetType == Integer.TYPE)
convertedValue = Integer.valueOf(value);
else
if(targetType == java/lang/Long || targetType == Long.TYPE)
convertedValue = Long.valueOf(value);
else
if(targetType == java/lang/Boolean || targetType == Boolean.TYPE)
convertedValue = Boolean.valueOf(value);
return convertedValue;
}

}


//PooledDataSource
public class PooledDataSource
implements DataSource
{
private final PoolState state;
private final UnpooledDataSource dataSource;
protected int poolMaximumActiveConnections;
protected int poolMaximumIdleConnections;
protected int poolMaximumCheckoutTime;
protected int poolTimeToWait;
protected String poolPingQuery;
protected boolean poolPingEnabled;
protected int poolPingConnectionsNotUsedFor;
private int expectedConnectionTypeCode;

}

从上面可以看出解析datasource节点,就是解析器属性,并初始化datasource,
PooledDataSourceFactory继承UnpooledDataSourceFactory,改变的只是数据源类型,
PooledDataSourceFactory对应的数据源为PooledDataSource,而UnpooledDataSourceFactory对应的为,UnpooledDataSource;
我们再来看解析environment节点是,environment的构造
 org.apache.ibatis.mapping.Environment.Builder environmentBuilder = 
(new org.apache.ibatis.mapping.Environment.Builder(id)).transactionFactory(txFactory).dataSource(dataSource);


//Environment
public final class Environment
{
private final String id;
private final TransactionFactory transactionFactory;
private final DataSource dataSource;

public static class Builder
{
public Environment build()
{
return new Environment(id, transactionFactory, dataSource);
}

private String id;
private TransactionFactory transactionFactory;
private DataSource dataSource;
public Builder(String id)
{
this.id = id;
}
}
}

再来看,Configuration设置environment
public void setEnvironment(Environment environment)
{
this.environment = environment;
}


总结:
[color=blue]事务类型为jdbc对应的事务工厂为JdbcTransactionFactory,由JdbcTransactionFactory,根据数据源,事务级别以及自动提交属性来,创建JdbcTransaction,而JdbcTransaction的事务管理,是通过数据连接connection,而connection是从datasource获取,JdbcTransaction的事务管理,就是依靠相应的数据库driver,来管理,实际依赖于数据库;解析datasource节点,就是解析器属性,并初始化datasource,PooledDataSourceFactory继承UnpooledDataSourceFactory,改变的只是数据源类型,PooledDataSourceFactory对应的数据源为PooledDataSource,而UnpooledDataSourceFactory对应的为,UnpooledDataSource。[/color]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值