Mybatis源码(一) 之SqlSession的创建
近日学习了mybatis的源码,记录一下sqlSessionFactory的创建过程,SqlSessionFactory 是通过SqlSessionFactoryBuilder创建的,如下所示
// 获取Mybatis配置文件输入流 Reader reader = Resources.getResourceAsReader("mybatis-config.xml"); // 通过SqlSessionFactoryBuilder创建SqlSessionFactory实例 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); // 调用SqlSessionFactory的openSession()方法,创建SqlSession实例 SqlSession session = sqlSessionFactory.openSession();
SqlSessionFactoryBuilder的相关源码如下:
public class SqlSessionFactoryBuilder { public SqlSessionFactory build(Reader reader) { return build(reader, null, null); } public SqlSessionFactory build(Reader reader, String environment) { return build(reader, environment, null); } public SqlSessionFactory build(Reader reader, Properties properties) { return build(reader, null, properties); } public SqlSessionFactory build(Reader reader, String environment, Properties properties) { try { XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties); return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { reader.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } } } public SqlSessionFactory build(InputStream inputStream) { return build(inputStream, null, null); } public SqlSessionFactory build(InputStream inputStream, String environment) { return build(inputStream, environment, null); } public SqlSessionFactory build(InputStream inputStream, Properties properties) { return build(inputStream, null, properties); } //通过XMLConfigBuilder解析mybatis配置,然后创建SqlSessionFactory对象 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 中主要就做了一个创建XPathParser解析器的工作,并把解析器放入到XMLConfigBuilder中
XMLConfigBuilder部分源码如下:
XmlConfigBuilder的parseConfiguration方法解析xml是根据Xpath方式解析的。解析相应的标签之后,又把属性赋值给Configuration对象。最后返回
public class XMLConfigBuilder extends BaseBuilder { private boolean parsed; private final XPathParser parser; private String environment; private final ReflectorFactory localReflectorFactory = new DefaultReflectorFactory(); public XMLConfigBuilder(Reader reader) { this(reader, null, null); } public XMLConfigBuilder(Reader reader, String environment) { this(reader, environment, null); } public XMLConfigBuilder(Reader reader, String environment, Properties props) { this(new XPathParser(reader, true, props, new XMLMapperEntityResolver()), environment, props); } public XMLConfigBuilder(InputStream inputStream) { this(inputStream, null, null); } public XMLConfigBuilder(InputStream inputStream, String environment) { this(inputStream, environment, null); } public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) { this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props); } private XMLConfigBuilder(XPathParser parser, String environment, Properties props) { super(new Configuration()); ErrorContext.instance().resource("SQL Mapper Configuration"); this.configuration.setVariables(props); this.parsed = false; this.environment = environment; this.parser = parser; } public Configuration parse() { // 防止parse()方法被同一个实例多次调用 if (parsed) { throw new BuilderException("Each XMLConfigBuilder can only be used once."); } parsed = true; // 调用XPathParser.evalNode()方法,创建表示configuration节点的XNode对象。 // 调用parseConfiguration()方法对XNode进行处理 parseConfiguration(parser.evalNode("/configuration")); return configuration; } // 解析mybatis-config文件中的标签 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); } }
由以上源码可知,build方法中XMLConfigBuilder 解析mybatis-config.xml文件得到Configuration对象。然后调用如下方法,创建的对象
SqlSessionFactory是一个接口,所以创建他的默认实现。DefaultSqlSessionFactory
public SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); }
SqlSessionFactory是一个接口,可以通过接口中的 SqlSession openSession(); 方法获取SqlSession的实例。
SqlSessionFactory接口代码
public interface SqlSessionFactory { SqlSession openSession(); SqlSession openSession(boolean autoCommit); SqlSession openSession(Connection connection); SqlSession openSession(TransactionIsolationLevel level); SqlSession openSession(ExecutorType execType); SqlSession openSession(ExecutorType execType, boolean autoCommit); SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level); SqlSession openSession(ExecutorType execType, Connection connection); Configuration getConfiguration(); }
SqlSession也是一个接口,DefaultSqlSession是其实现类
选择实现类 DefaultSqlSessionFactory 源码片段
public class DefaultSqlSessionFactory implements SqlSessionFactory { private final Configuration configuration; public DefaultSqlSessionFactory(Configuration configuration) { this.configuration = configuration; } @Override public SqlSession openSession() { return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false); } private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; try { // 获取Mybatis主配置文件配置的环境信息 final Environment environment = configuration.getEnvironment(); // 创建事务管理器工厂 final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); // 创建事务管理器 tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); // 根据Mybatis主配置文件中指定的Executor类型创建对应的Executor实例 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(); } } }
由此,SqlSession的实例就创建完成了
给自己画个粗糙的流程图