MyBatis原始碼分析:SqlSession獲取過程
阿新 • • 發佈:2019-01-26
public static void main(String[] args) throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//SqlSessionFactory初始化
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
//獲取SqlSession
SqlSession session = factory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = userMapper.getUserById("1");
System.out.println(user);
}
1、SqlSessionFactory初始化過程
//class:SqlSessionFactoryBuilder
public SqlSessionFactory build (InputStream inputStream, String environment, Properties properties) {
try {
//建立XML解析器來解析xml配置檔案
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
//parser.parse()解析xml檔案
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.
}
}
}
//返回包含了Configuration的DefaultSqlSession物件。
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
//把配置檔案的資訊解析並儲存在Configuration物件中
public Configuration parse() {
//如果已經解析過了,丟擲異常
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
//配置檔案的根節點是configuration
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
解析配置檔案:
分步驟解析xml檔案的各個節點
private void parseConfiguration(XNode root) {
try {
Properties settings = settingsAsPropertiess(root.evalNode("settings"));
//issue #117 read properties first
//解析properties
propertiesElement(root.evalNode("properties"));
//解析settings
loadCustomVfs(settings);
//解析typeAliases,類型別名
typeAliasesElement(root.evalNode("typeAliases"));
//解析外掛
pluginElement(root.evalNode("plugins"));
//解析物件工廠
objectFactoryElement(root.evalNode("objectFactory"));
//解析物件包裝工廠
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
//解析reflectorFactory
reflectorFactoryElement(root.evalNode("reflectorFactory"));
//把settings裡各個所有設定設定到configruation上
settingsElement(settings);
// read it after objectFactory and objectWrapperFactory issue #631
//解析environments
environmentsElement(root.evalNode("environments"));
//解析databaseIdProvider
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
//解析typeHandlers,型別處理器
typeHandlerElement(root.evalNode("typeHandlers"));
//解析mappers
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
Mybatis會把配置檔案的所有資訊都儲存在Configuration物件中,並返回包含了configuration的DefualtSqlSessionFactoryd物件
configuration物件:
主要過程:
解析xml的每一個資訊儲存在Configuration中,返回包含Configuration的DefaultSqlSessionFactory;
2、SqlSession獲取
SqlSession session = factory.openSession();
//class:DefaultSqlSessionFactory
@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);
//構建DefaultSqlSession物件並返回
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();
}
}
執行器Executor建立過程:
//根據傳入的ExecutorType來構建不同的Executor,可以在配置檔案中配置,預設是SIMPLE
//final Executor executor = configuration.newExecutor(tx, execType);
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
//如果要求快取,生成另一種CachingExecutor(預設就是有快取),裝飾者模式,所以預設都是返回CachingExecutor
if (cacheEnabled) {
executor = new CachingExecutor(executor);
}
//此處呼叫外掛,通過外掛可以改變Executor行為,採用的是責任鏈模式,來產生代理物件
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
SqlSession物件中包含configuration和executor
主要過程:
1、根據ExecutorType建立Executor,預設是SIMPLE型別的,但因為cacheEnabled預設是為true的,所以實際上生成的是CachingExecutor,裡面包含了一個Executor,使用了裝飾者模式;
2、返回一個DefaultSqlSession物件,該物件包含Configuration和Executor;