Mybatis源码解析之核心类分析
Mybatis的初始化过程就是mybatis配置文件的解析过程并将解析结果保存到Configuration类。
configuation是mybatis配置文件的根节点。
configuration 配置
-properties 属性
-settings 设置
-typeAliases 类型别名
-typeHandlers 类型处理器
-objectFactory 对象工厂
-plugins 插件
-environments 环境
-environment 环境变量
-transactionManager 事务管理器
-dataSource 数据源
-databaseIdProvider 数据库厂商标识
-mappers 映射器
本文主要讲解源码,不对配置文件展开,详细内容可以参考http://www.mybatis.org/mybatis-3/zh/configuration.html#
下文代码是mybatis通过解析xml配置文件进行初始化的一个简单demo,后续我们将根据这个demo追踪mybatis源码的处理过程。
InputStream inputStream = Resources.getResourceAsStream("mybatis-coonfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
SqlSessionFactoryBuilder的build(inputStream)方法通过调用同名的重载方法SqlSessionFactoryBuilder#build(InputStream, String. Properties)来生成需要的SqlSessionFacotry。
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
首先,通过XmlConfigBuilder解析配置文件,并得到configuration类对象。
然后根据configuration作为参数调用build得到所需的SqlSessionFactory,可以看到最终得到的SqlSessionFactory类型是DefaultSqlSessionFactory。
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
private void parseConfiguration(XNode root) {
try {
//issue #117 read properties first
propertiesElement(root.evalNode("properties"));
Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfs(settings);
typeAliasesElement(root.evalNode("typeAliases"));
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectorFactoryElement(root.evalNode("reflectorFactory"));
settingsElement(settings);
// read it after objectFactory and objectWrapperFactory issue #631
environmentsElement(root.evalNode("environments"));
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
typeHandlerElement(root.evalNode("typeHandlers"));
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
可以看到,XMLConfigBuilder对xml配置文件中对configuration的子节点进行逐个解析。
以typeAliases为例,遍历typeAliases的子节点,根据配置情况将其加入到configuration对象中对应的typeAliasRegistry属性,其它节点的解析也类似。
private void typeAliasesElement(XNode parent) {
if (parent != null) {
for (XNode child : parent.getChildren()) {
if ("package".equals(child.getName())) {
String typeAliasPackage = child.getStringAttribute("name");
configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage);
} else {
String alias = child.getStringAttribute("alias");
String type = child.getStringAttribute("type");
try {
Class> clazz = Resources.classForName(type);
if (alias == null) {
typeAliasRegistry.registerAlias(clazz);
} else {
typeAliasRegistry.registerAlias(alias, clazz);
}
} catch (ClassNotFoundException e) {
throw new BuilderException("Error registering typeAlias for '" + alias + "'. Cause: " + e, e);
}
}
}
}
}
@Override
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
closeTransaction(tx); // may have fetched a connection so lets call close()
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
DefaultSqlSessionFactory#openSession()最终通过DefaultSqlSessionFactory#openSessionFromDataSource(ExecutorType, TransactionLevel, boolean)试下,可以看到最后获得的SqlSession类型是DefaultSqlSession,其中executor类型是SimpleExecutor。