Mybatis原始碼(一) 之SqlSession的建立
阿新 • • 發佈:2020-08-21
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); } }
由以上原始碼可知,SqlSessionFactory 是通過XMLConfigBuilder 解析mybatis配置檔案後,得到的
XMLConfigBuilder部分原始碼如下:
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); } }
SqlSessionFactory是一個介面,可以通過介面中的SqlSession openSession(); 方法獲取SqlSession的例項。SqlSession也是一個介面,DefaultSqlSession是其實現類
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(); }
選擇實現類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的例項就建立完成了