Mybatis源码之数据源模块分析
先來看看java純jdbc查詢數(shù)據(jù)的示例:
try {//加載對(duì)應(yīng)的驅(qū)動(dòng)類Class.forName("com.mysql.cj.jdbc.Driver");//創(chuàng)建連接Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC", "root", "root123");String sql = "select * from t_user";//創(chuàng)建statementStatement createStatement = connection.createStatement();//利用statement執(zhí)行SQL語句返回結(jié)果集ResultSet rs = createStatement.executeQuery(sql);//遍歷結(jié)果集while(rs.next()) {System.out.print(rs.getString(1) + " > ");System.out.print(rs.getString(2) + " > ");System.out.print(rs.getString(3) + " > ");System.out.println(rs.getString(4));}//關(guān)閉rs.close();createStatement.close();connection.close(); } catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace(); } catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace(); }這是一個(gè)最基礎(chǔ)的查詢數(shù)據(jù)的示例,也是所有的使用Java ORM框架與數(shù)據(jù)庫交互的底層,只不過是封裝一下罷了,但是像這種使用DriverManager創(chuàng)建連接的方式,已經(jīng)基本淘汰了,在應(yīng)用中是比較浪費(fèi)資源的,所以JDK就提供一種數(shù)據(jù)庫連接池接口,供第三方組件實(shí)現(xiàn),java.sql.DataSource,這個(gè)僅僅是個(gè)接口,具體的連接池的實(shí)現(xiàn)需第三方進(jìn)行實(shí)現(xiàn)。
我們就直接先看一下Mybatis中的數(shù)據(jù)源連接池是怎么實(shí)現(xiàn)的。
設(shè)計(jì)模式
我們現(xiàn)需要了解一下數(shù)據(jù)源模塊中的設(shè)計(jì)模式
工廠模式(Factory Pattern)
是 Java 中最常用的設(shè)計(jì)模式之一。這種類型的設(shè)計(jì)模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對(duì)象的最佳方式。
在工廠模式中,我們在創(chuàng)建對(duì)象時(shí)不會(huì)對(duì)客戶端暴露創(chuàng)建邏輯,并且是通過使用一個(gè)共同的接口來指向新創(chuàng)建的對(duì)象。
UML:
但是這種工廠模式存在一定的弊端,比如在新增一個(gè)新業(yè)務(wù)模塊的時(shí)候,是必須修改創(chuàng)建工廠的代碼,違反了開閉原則。
所以就有一種新澤設(shè)計(jì)模式,
抽象工廠模式(Abstract Factory Pattern)
是圍繞一個(gè)超級(jí)工廠創(chuàng)建其他工廠。該超級(jí)工廠又稱為其他工廠的工廠。這種類型的設(shè)計(jì)模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對(duì)象的最佳方式。
在抽象工廠模式中,接口是負(fù)責(zé)創(chuàng)建一個(gè)相關(guān)對(duì)象的工廠,不需要顯式指定它們的類。每個(gè)生成的工廠都能按照工廠模式提供對(duì)象。
當(dāng)業(yè)務(wù)擴(kuò)展的時(shí)候新增擴(kuò)展的工廠,無需修改工廠代碼,Mybatis的數(shù)據(jù)源模塊就是使用的抽象工廠設(shè)計(jì)模式。
源碼分析
在源碼中超級(jí)工廠如下:
package org.apache.ibatis.datasource;import java.util.Properties;import javax.sql.DataSource;/*** @author Clinton Begin*/ public interface DataSourceFactory {void setProperties(Properties props);DataSource getDataSource();}設(shè)計(jì)的UML如下(一個(gè)工廠類對(duì)應(yīng)只生產(chǎn)一種數(shù)據(jù)源):
JndiDataSourceFactory:是一個(gè)引用,可以直接獲取應(yīng)用級(jí)容器中的上下文數(shù)據(jù)源。
UnpooledDataSourceFactory:生產(chǎn)UnpooledDataSource的數(shù)據(jù)源工廠,單一連接,非使用了數(shù)據(jù)源連接池。
PooledDataSourceFactory:生產(chǎn)PooledDataSource數(shù)據(jù)源工廠,提供了一個(gè)線程安全的數(shù)據(jù)源連接池。
UnpooledDataSource
雖說是繼承了DataSource但是并沒有具體的實(shí)現(xiàn)了連接池的特性,可以看一下這個(gè)是怎么產(chǎn)出Connection
跟開始那個(gè)JDBC連接數(shù)據(jù)庫的示例是一致的用法。
PooledDataSource
這個(gè)就是真正的數(shù)據(jù)源連接池的實(shí)現(xiàn)
連接池需要比較多的參數(shù)設(shè)置,比如超時(shí),檢測連接是否有效,活動(dòng)的連接,空閑連接等等。
所以今天就講講比較核心的一些東西:
里面創(chuàng)建連接是通過創(chuàng)建UnpooledDataSource對(duì)象來產(chǎn)出連接的,連接主要是存于List當(dāng)中,然后配合一系列的操作就變成了線程安全的連接池了,
但是Mybatis的連接池的連接并非直接的使用的Connection而是使用的PooledConnection,進(jìn)去發(fā)現(xiàn)這個(gè)是個(gè)連接代理,給真正的連接進(jìn)行了代理增強(qiáng)
連接池釋放連接的過程
連接池獲取連接的過程(這個(gè)就比較長了)
這里用到了并發(fā)編程的知識(shí),大家可以看看我之前發(fā)布的博文,有講解這一塊的東西
進(jìn)行校驗(yàn)后會(huì)將當(dāng)前的線程添加到活動(dòng)連接集合當(dāng)中,
在獲取PooledConnection對(duì)象后,獲取的連接是代理的連接
解析基本結(jié)束了。
最后要提一下為什么在JDBC中使用連接只要用DriverManager.getConnection就能獲取連接了,
因?yàn)樵贑lass.forName("")加載的時(shí)候會(huì)去加載驅(qū)動(dòng)類的靜態(tài)代碼塊,將其驅(qū)動(dòng)放到registeredDrivers集合中,這個(gè)是個(gè)CopyOnWriteArrayList讀寫分離集合
然后在DriverManager獲取連接
總結(jié)
以上是生活随笔為你收集整理的Mybatis源码之数据源模块分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 基于Spring Boot不同的环境使用
- 下一篇: Mysql 使用正则表达式
