以前學習到數據庫
DefaultSqlSessionFactory中的session
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, autoCommit); return new DefaultSqlSession(configuration, executor); } 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(); } }
在此方法中,TransactionFactory依賴於Environment類,Transaction由Transaction Factory生成,Executor依賴於Transaction,最後DefaultSqlSession到業務層使用。app
可見Environment做爲獲取SqlSession的基礎,在如今觀察到的代碼中,Configuration始終貫穿代碼之中。ide
隨之查看Environment的源碼,源碼分析
屬性只有學習
private final String id; private final TransactionFactory transactionFactory; private final DataSource dataSource;
Environment依然使用Builder模式。fetch
由此屬性看來,Environment關注的是事務類型,還有就是數據源,id使用與區分,參考文檔中介紹了能夠經過多個Environment實現多數據庫的操做。ui
跟蹤Environment的build方式,是由spa
XMLConfigBuilder中的xml
private void parseConfiguration(XNode root) { try { propertiesElement(root.evalNode("properties")); //issue #117 read properties first typeAliasesElement(root.evalNode("typeAliases")); pluginElement(root.evalNode("plugins")); objectFactoryElement(root.evalNode("objectFactory")); objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); settingsElement(root.evalNode("settings")); environmentsElement(root.evalNode("environments")); // read it after objectFactory and objectWrapperFactory issue #631 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); } }
方法中的environmentsElement(root.evalNode("environments")); 生成Environment的。
private void environmentsElement(XNode context) throws Exception { if (context != null) { if (environment == null) { environment = context.getStringAttribute("default"); } for (XNode child : context.getChildren()) { String id = child.getStringAttribute("id"); if (isSpecifiedEnvironment(id)) { TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager")); DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource")); DataSource dataSource = dsFactory.getDataSource(); Environment.Builder environmentBuilder = new Environment.Builder(id) .transactionFactory(txFactory) .dataSource(dataSource); configuration.setEnvironment(environmentBuilder.build()); } } } }
來到此處終於找到參考文檔中的基本配置要素了!environments元素,transactionManager元素,dataSource元素。
在SqlSessionFactoryBuilder中,
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); return build(parser.parse());
經過輸入流,生成XMLConfigBuilder,XMLConfigBuilder的parse方法調用了
parseConfiguration方法設置Congfiguration並返回,並經過SqlSessionFactoyBuilder生成
DefaultSqlSessionFactory(此時SqlSessionFacoty已生成SqlSession)。
至此就完成了SqlSessionFactory生成SqlSession的源碼分析了。
算是解答了我以前想到的幾個問題了,SqlSessionFactoryBuilder,SqlSessionFacotyBuilder,基本xml的配置。
以後應該要分析一下在這過程當中代碼中寫得優雅的部分。