原理图
Mybatis通过Resources加载全局配置文件。接着实例化SqlSessionFactoryBuilder,采用构建者设计模式帮助SqlSessionFactory接口实现DefaultSqlSessionFactory
实例化DefaultSqlSessionFactory之前需要先创建XMLConfigBuilder解析全局配置文件流,并把解析结果存放在Configuration中,之后把Configuration传递给DefaultSqlSessionFactory
到此SqlSessionFactory创建完成。
接下来由SqlSessionFactory创建SqlSession
每次创建SqlSession时,都要由TransactionFactory创建一个Transaction对象,同时还需要创建SqlSession的执行器Executor,最后实例化DefaultSqlSession,传递给SqlSession接口。
最后根据项目需求使用SqlSession接口的API完成具体事务操作,根据事务执行成功与否执行相应的逻辑。
源码
下面是我们使用mybatis时需要写的三行代码:
InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream );
SqlSession session = factory.openSession();
我们看build这个方法,跟进源码:
发现这个函数返回了一个build方法,继续跟入该build方法
这段代码中我们可以看到,我们传入的配置文件由XMLConfigBuilder接收,在这个方法里第一句就是创建XMLConfigBuilder对象parser,然后同样返回了一个build方法,build方法的参数为parser.parse(),跟进parse方法
在parse方法里调用了parseConfiguration,我们可以看到parseConfiguration方法里面就是在解析我们在XML中配置的基本信息。
原路回到parse方法里,我们看到它返回了一个configuration,证明了XMLConfigBuilder最后是把在parseConfiguration方法中解析出来的信息封装到了configuration对象中
原路返回上一个build方法,如下图
跟进build(parser.parse())的build方法,发现他跳到了正下面的方法,在这个方法里传入了一个Configuration对象,这个对象就是parser解析后返回的配置文件
并且方法体里实例化SqlSessionFactory这个接口为DefaultSqlSessionFactory,把Configuration对象传了进去并返回。
到此SqlSessionFactory创建完成
继续看第三句代码:
SqlSession session = factory.openSession();
跟入openSession,选择Open Implementation,再选择DefaultSqlSessionFactory,进入如下代码
继续跟入openSessionFromDataSource
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();
}
}
我们可以看到,第一句创建了一个Transaction对象,接着通过configuration对象创建environment对象,然后创建transactionFactory,通过该事务工厂实例化Transaction对象。
然后通过configuration对象创建执行器executor
最后实例化SqlSession为DefaultSqlSession,并且传入configuration以及刚刚创建的执行器executor,以及事务提交机制autoCommit自动提交。
到此为止完成了SqlSession的实例化。
总结
通过源码的解读更加深刻的理解了SqlSessionFactory和SqlSession的实例化过程,博主跟源码跟的并不深,但通过这几段简单的源码的阅读还是有很大的收获。