<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # Mybatis深入之DataSource實例化過程 ### 簡介 主要介紹Mybatis啟動過程中DataSource實例化的過程、為后面解析一個完整SQL執行過程做個前章。 ### Mybatis中DataSource體系 ### MybatisDataSource整體簡介 Mybatis中關于數據庫的類都在`org.apache.ibatis.datasource`包中 ![DataSource體系](https://box.kancloud.cn/2016-08-08_57a85803a27fa.jpg "") Mybatis配置文件中關于數據庫的配置: ~~~ <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> ~~~ - 重點關注`<dataSource type="POOLED">`的type屬性、其有三種取值: - POOLED:使用Mybatis自帶的數據庫連接池來管理數據庫連接 - UNPOOLED:不使用任何數據庫連接池來管理數據庫連接 - JNDI:jndi形式使用數據庫連接、主要用于項目正常使用的時候 類與類之間的關系: ![這里寫圖片描述](https://box.kancloud.cn/2016-08-08_57a85803b30c3.jpg "") 每一條線都是一種關系、簡單解釋一下 1. PooledDataSource實現java.sql.DataSource接口 2. PooledDataSource內部持有一個DataSource引用 3. UnpooledDataSource實現java.sql.DataSource接口 4. PooledDataSource內部持有一個UnpooledDataSource引用 5.PooledDataSourceFactory無參構造方法體中將其父類UnpooledDataSourceFactory持有的引用DataSource實例化為PooledDataSource 6. PooledDataSourceFactory繼承UnpooledDataSourceFactory 7. UnpooledDataSourceFactory無參構造方法將其持有的引用DataSource實例化為UnpooledDataSource 8. UnpooledDataSourceFactory持有一個DataSource引用、用于返回實例化好的DataSource。 ### Mybatis中DataSource實例化整體過程 這里以使用Mybatis自帶的數據庫連接池為例。也就是type為 “POOLED”類型的數據連接。 1. 根據配置文件中type的類型實例化具體的DataSourceFactory。這里是POOLED所以實例化的是PooledDataSourceFactory。 1. 通過PooledDataSourceFactory來獲取DataSource具體實例:PooledDataSource 對于第一步更詳細點的過程: - 在Mybatis初始化Configuration對象時、Configuration中屬性TypeAliasRegistry同樣被實例化、并且在Configuration的無參構造方法中對TypeAliasRegistry注冊了許多常用的類(以鍵值對的形式保存在TypeAliasRegistry的屬性`private final Map<String, Class<?>> TYPE_ALIASES = new HashMap<String, Class<?>>();`中、也包括TypeAliasRegistry無參構造方法注冊的基本java類型。 - 通過配置文件中type指定的”POOLED”在TypeAliasRegistry中查找其對應的類:PooledDataSourceFactory - 調用其newInstance()實例化 - PooledDataSourceFactory繼承自UnpooledDataSourceFactory、所以UnpooledDataSourceFactory先被實例化、 - UnpooledDataSourceFactory無參構造方法中實例化了其DataSource引用為UnpooledDataSource。 - 接著實例化PooledDataSourceFactory、其無參構造方法體將父類UnpooledDataSourceFactory持有的DataSource實例化為PooledDataSource。 - PooledDataSource實例化時初始化了一些關于數據庫連接池的配置信息 - PooledDataSource的無參構造方法中將其持有的UnpooledDataSource實例化。 - UnpooledDataSource中關于數據庫連接的屬性值在實例化DataSourceFactory之后讀取properties值設置到對應屬性上。 ### 具體過程 從上一篇中知道Mybatis初始化過程是解析Mybatis配置文件并裝配Configuration對象。從Mybatis基礎使用中知道Mybatis數據庫連接信息的配置是在environments標簽中配置的: ~~~ <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> ~~~ 所以想要了解DataSource初始化過程可以從XMLConfigBuilder中的parse方法入手: ~~~ 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()); } } } } ~~~ - 這里同樣有關于數據庫事務的配置、具體事務有關的后面再說 - 主要看如何實例化DataSource、同樣從上面代碼中我們知道只是將DataSource實例化了而沒有進行任何操作、原因是只有具體執行某SQL語句的時候才會使用DataSource來獲取數據庫連接。 獲取DataSource關鍵代碼: ~~~ DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource")); DataSource dataSource = dsFactory.getDataSource(); ~~~ - 根據配置文件中dataSource標簽中內容實例化DataSourceFactory - 通過DataSourceFactory獲取DataSource 下面首先看如何根據dataSource標簽內容實例化DataSourceFactory ~~~ private DataSourceFactory dataSourceElement(XNode context) throws Exception { if (context != null) { //獲取數據庫連接池類型: POOLED-使用Mybatis自帶數據庫連接池。UNPOOL-不使用數據庫連接池。這里看POOLED的情況。 String type = context.getStringAttribute("type"); Properties props = context.getChildrenAsProperties(); DataSourceFactory factory = (DataSourceFactory) resolveClass(type).newInstance(); factory.setProperties(props); return factory; } throw new BuilderException("Environment declaration requires a DataSourceFactory."); } ~~~ - 上面一段代碼關鍵點在于`resolveClass(type)` - 經過一系列的方法調用、最終返回結果的方法是:`TypeAliasRegistry` ~~~ @SuppressWarnings("unchecked") // throws class cast exception as well if types cannot be assigned public <T> Class<T> resolveAlias(String string) { try { if (string == null) return null; String key = string.toLowerCase(Locale.ENGLISH); // issue #748 Class<T> value; if (TYPE_ALIASES.containsKey(key)) { value = (Class<T>) TYPE_ALIASES.get(key); } else { value = (Class<T>) Resources.classForName(string); } return value; } catch (ClassNotFoundException e) { throw new TypeException("Could not resolve type alias '" + string + "'. Cause: " + e, e); } } ~~~ - 這里重點在于TypeAliasRegistry是何時實例化的 - 上一篇初始化過程中知道Configuration中有一個私有變量`protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();` - 進一步看看Configuration實例化的時候其無參構造函數體就知道其緣由 ~~~ public Configuration() { typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class); typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class); typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class); typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class); typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class); typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class); typeAliasRegistry.registerAlias("FIFO", FifoCache.class); typeAliasRegistry.registerAlias("LRU", LruCache.class); typeAliasRegistry.registerAlias("SOFT", SoftCache.class); typeAliasRegistry.registerAlias("WEAK", WeakCache.class); typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class); typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class); typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class); typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class); typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class); typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class); typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class); typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class); typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class); typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class); typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class); typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class); languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class); languageRegistry.register(RawLanguageDriver.class); } ~~~ - 從上面可以看出TypeAliasRegistry在實例化之后并初始化了其內部私有變量`private final Map<String, Class<?>> TYPE_ALIASES = new HashMap<String, Class<?>>();`來保存一些Type alias(類型別名)供后面程序使用。 從上面代碼`typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);`可以看出最后返回的是`PooledDataSourceFactory`。 ~~~ public class PooledDataSourceFactory extends UnpooledDataSourceFactory { public PooledDataSourceFactory() { this.dataSource = new PooledDataSource(); } } ~~~ - PooledDataSourceFactory繼承UnpooledDataSourceFactory 其中UnpooledDataSourceFactory擁有一個DataSource的protected級別的屬性`protected DataSource dataSource;`并且其構造函數: ~~~ public UnpooledDataSourceFactory() { this.dataSource = new UnpooledDataSource(); } ~~~ 對比PooledDataSourceFactory的構造函數: ~~~ public PooledDataSourceFactory() { this.dataSource = new PooledDataSource(); } ~~~ 知道最終UnpooledDataSourceFactory的`protected DataSource dataSource;`實例是:`PooledDataSource`。 到這里只要知道PooledDataSource是什么、那么返回的DataSource就是什么。 當然在這之前還需要一步、就是將配置文件中的數據庫連接信息設置到最后生成的DataSourceFactory(在這里就是PooledDataSourceFactory)中去。這個過程中使用了一個Mybatis很長用的用于操作反射的封裝類:MetaObject。提供了一些簡便的獲取、設置類等通過反射來操作類的方法、以后有時間專門看一眼。 下面的主要目標就是看PooledDataSource調用其無參構造方法時到底做了什么。 PooledDataSource是java.sql.DataSource的一個實現類、其屬性與無參構造方法如下: ~~~ private static final Log log = LogFactory.getLog(PooledDataSource.class); private final PoolState state = new PoolState(this); private final UnpooledDataSource dataSource; // OPTIONAL CONFIGURATION FIELDS protected int poolMaximumActiveConnections = 10; protected int poolMaximumIdleConnections = 5; protected int poolMaximumCheckoutTime = 20000; protected int poolTimeToWait = 20000; protected String poolPingQuery = "NO PING QUERY SET"; protected boolean poolPingEnabled = false; protected int poolPingConnectionsNotUsedFor = 0; private int expectedConnectionTypeCode; public PooledDataSource() { dataSource = new UnpooledDataSource(); } ~~~ - 設置了一些作為數據庫連接池初始化使用的參數 - 無參方法體中實例話了屬性`dataSource = new UnpooledDataSource();` - UnpooledDataSource無參構造函數是空方法題 - 要注意的是:前面實例化DataSourceFactory的時候最后一步是設置屬性。其實就是通過MetaObject來將屬性值設置到UnpooledDataSource的數據庫連接屬性上了。 到這里、關于數據庫DataSource類的實例話也就結束了。 ### 補充 ### 對數據庫實例化做個總結: 當使用數據庫連接池時、即`<dataSource type="POOLED">`時、DataSourceFactory具體實例是PooledDataSourceFactory。返回的DataSource具體實例是內部持有UnpooledDataSource實例的PooledDataSource。 當不使用數據庫連接池時、即`<dataSource type="UNPOOLED">` 時、DataSourceFactory具體實例是UnpooledDataSourceFactory。返回的DataSource具體實例是UnpooledDataSource實例。 更多內容:[Mybatis 目錄](http://blog.csdn.net/crave_shy/article/details/45825599)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看