做網(wǎng)站的目標(biāo)是什么大型網(wǎng)站制作
【面試精講】MyBatis設(shè)計(jì)模式及源碼分析,MyBatis設(shè)計(jì)模式實(shí)現(xiàn)原理
目錄
本文導(dǎo)讀
一、MyBatis中運(yùn)用的設(shè)計(jì)模式詳解
1. 工廠模式(Factory Pattern)
2. 單例模式(Singleton Pattern)
3. 建造者模式(Builder Pattern)
4. 代理模式(Proxy Pattern)
5. 模板方法模式(Template Method Pattern)
6. 策略模式(Strategy Pattern)
7. 觀察者模式(Observer Pattern)
二、MyBatis設(shè)計(jì)模式的源碼實(shí)現(xiàn)原理
工廠模式的應(yīng)用 -?SqlSessionFactory
單例模式的應(yīng)用 -?SqlSessionFactory
代理模式的應(yīng)用 - Mapper動(dòng)態(tài)代理
建造者模式(Builder Pattern)
策略模式 - Strategy Pattern
觀察者模式 - Observer Pattern
三、MyBatis源碼解析
工廠模式 -?SqlSessionFactoryBuilder
單例模式 -?SqlSessionFactory
代理模式 -?MapperProxyFactory
總結(jié)
?博主v:XiaoMing_Java
本文導(dǎo)讀
MyBatis是一個(gè)流行的持久層框架,它極大地簡化了數(shù)據(jù)庫操作,提升了開發(fā)效率。在其底層實(shí)現(xiàn)中,MyBatis廣泛采用了各種設(shè)計(jì)模式,這些設(shè)計(jì)模式不僅增加了框架的靈活性和可維護(hù)性,也為開發(fā)人員提供了豐富的使用場景和擴(kuò)展能力。本文將深入探討MyBatis所應(yīng)用的主要設(shè)計(jì)模式及其在框架中的具體應(yīng)用。
一、MyBatis中運(yùn)用的設(shè)計(jì)模式詳解
1. 工廠模式(Factory Pattern)
工廠模式是一種創(chuàng)建型模式,它提供了一種創(chuàng)建對(duì)象的最佳方式。在MyBatis中,SqlSessionFactoryBuilder
、SqlSessionFactory
等關(guān)鍵組件的創(chuàng)建過程就運(yùn)用到了工廠模式。尤其是SqlSessionFactory
的創(chuàng)建,它是通過SqlSessionFactoryBuilder
讀取MyBatis配置文件并構(gòu)建出SqlSessionFactory
實(shí)例。這樣做可以隔離復(fù)雜的初始化過程,使用戶只需關(guān)注最終產(chǎn)出,而無需了解創(chuàng)建實(shí)例的復(fù)雜過程。
2. 單例模式(Singleton Pattern)
單例模式確保一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)全局訪問點(diǎn)。在MyBatis中,SqlSessionFactory
的設(shè)計(jì)就是單例模式的經(jīng)典應(yīng)用。一旦通過SqlSessionFactoryBuilder
創(chuàng)建了SqlSessionFactory
實(shí)例后,該實(shí)例就會(huì)在應(yīng)用程序中被復(fù)用,避免了重復(fù)創(chuàng)建實(shí)例帶來的資源浪費(fèi)。
3. 建造者模式(Builder Pattern)
建造者模式旨在將一個(gè)復(fù)雜對(duì)象的構(gòu)建與其表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。MyBatis中的XMLConfigBuilder
、XMLMapperBuilder
等類的設(shè)計(jì)采用了建造者模式。這些Builder類負(fù)責(zé)解析MyBatis的配置文件和映射文件,逐步構(gòu)建出配置信息和映射信息。通過建造者模式,MyBatis將復(fù)雜的解析過程分解成一系列的步驟,使得代碼更加清晰和易于維護(hù)。
4. 代理模式(Proxy Pattern)
代理模式為其他對(duì)象提供一個(gè)代理以控制對(duì)這個(gè)對(duì)象的訪問。MyBatis中對(duì)Mapper接口的實(shí)現(xiàn)就是基于JDK動(dòng)態(tài)代理機(jī)制。當(dāng)調(diào)用Mapper接口的方法時(shí),實(shí)際上是由MyBatis生成的代理類去執(zhí)行。這種方式允許MyBatis在執(zhí)行Mapper方法前后插入自定義邏輯,如開啟事務(wù)、處理緩存等,從而大幅提升了靈活性和可擴(kuò)展性。
5. 模板方法模式(Template Method Pattern)
模板方法模式定義了一個(gè)操作中的算法的骨架,而將一些步驟延遲到子類中。MyBatis的BaseExecutor
類就是一個(gè)模板方法模式的例證。它定義了數(shù)據(jù)庫操作的基本流程,如查詢、更新、提交事務(wù)等,而具體的執(zhí)行邏輯則留給其子類(比如SimpleExecutor
、BatchExecutor
等)去實(shí)現(xiàn)。這樣做的好處是復(fù)用了代碼,同時(shí)又保留了靈活性。
6. 策略模式(Strategy Pattern)
策略模式定義了一系列的算法,并將每一個(gè)算法封裝起來,使它們可以相互替換。MyBatis中的緩存策略、加載策略等正是策略模式的應(yīng)用。例如,MyBatis允許用戶配置不同的緩存實(shí)現(xiàn)(如EHCache、OSCache等),并在運(yùn)行時(shí)根據(jù)配置動(dòng)態(tài)選擇。這種模式使得MyBatis具有很高的靈活性和擴(kuò)展性。
7. 觀察者模式(Observer Pattern)
觀察者模式定義了一種依賴關(guān)系,當(dāng)一個(gè)對(duì)象狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并被自動(dòng)更新。在MyBatis中,Configuration
對(duì)象就是一個(gè)觀察者,它會(huì)監(jiān)聽映射文件的解析事件,并在解析完成后更新自己的狀態(tài)。通過觀察者模式,MyBatis能夠動(dòng)態(tài)響應(yīng)配置信息的變化,增強(qiáng)了框架的動(dòng)態(tài)性和靈活性。
以上便是MyBatis中常見的幾種設(shè)計(jì)模式及其應(yīng)用。這些設(shè)計(jì)模式的運(yùn)用大大提升了MyBatis的內(nèi)聚性、可擴(kuò)展性和靈活性,使得MyBatis成為了Java領(lǐng)域廣泛使用的ORM框架之一。
二、MyBatis設(shè)計(jì)模式的源碼實(shí)現(xiàn)原理
在第一部分中,我們討論了MyBatis使用的一些關(guān)鍵設(shè)計(jì)模式及其作用。現(xiàn)在,我們將深入探索這些設(shè)計(jì)模式在MyBatis源碼中的具體實(shí)現(xiàn)原理。
工廠模式的應(yīng)用 -?SqlSessionFactory
實(shí)現(xiàn)原理:
SqlSessionFactory
的創(chuàng)建是通過SqlSessionFactoryBuilder
完成的。這個(gè)過程遵循了典型的工廠模式設(shè)計(jì),SqlSessionFactoryBuilder
充當(dāng)工廠的角色,負(fù)責(zé)生產(chǎn)SqlSessionFactory
對(duì)象。
public SqlSessionFactory build(Reader reader) {// 使用XMLConfigBuilder解析配置文件XMLConfigBuilder parser = new XMLConfigBuilder(reader, null, null);return build(parser.parse());
}
在上述代碼中,build
方法首先通過XMLConfigBuilder
解析給定的配置文件,然后根據(jù)解析結(jié)果構(gòu)建出一個(gè)SqlSessionFactory
實(shí)例。這個(gè)過程封裝了對(duì)象的創(chuàng)建邏輯,使得客戶端代碼無需直接與對(duì)象的創(chuàng)建細(xì)節(jié)打交道。
單例模式的應(yīng)用 -?SqlSessionFactory
實(shí)現(xiàn)原理:
在MyBatis中,通常我們會(huì)將SqlSessionFactory
作為單例存在,以保證全局只有一個(gè)數(shù)據(jù)庫連接池,從而節(jié)省資源。、
public class MyBatisUtil {private static SqlSessionFactory sqlSessionFactory;static {try (InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml")) {sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);} catch (IOException e) {throw new ExceptionInInitializerError(e);}}public static SqlSessionFactory getSqlSessionFactory() {return sqlSessionFactory;}
}
在這段代碼中,利用靜態(tài)初始化塊加載配置并創(chuàng)建SqlSessionFactory
,確保了其單例性。此外,通過提供一個(gè)靜態(tài)方法getSqlSessionFactory
來全局訪問該實(shí)例,進(jìn)一步體現(xiàn)了單例模式的特點(diǎn)。
代理模式的應(yīng)用 - Mapper動(dòng)態(tài)代理
實(shí)現(xiàn)原理:
MyBatis中對(duì)Mapper接口的實(shí)現(xiàn)是基于JDK動(dòng)態(tài)代理的。當(dāng)調(diào)用Mapper接口的方法時(shí),實(shí)際上是委托給了由MyBatis動(dòng)態(tài)生成的代理類。
public class MapperProxy<T> implements InvocationHandler {private final SqlSession sqlSession;private final Class<T> mapperInterface;public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 方法調(diào)用的處理邏輯if (Object.class.equals(method.getDeclaringClass())) {return method.invoke(this, args);}// 執(zhí)行SQL操作return sqlSession.selectList(mapperInterface.getCanonicalName() + "." + method.getName());}
}
建造者模式(Builder Pattern)
MyBatis在處理配置文件時(shí),使用了建造者模式。XMLConfigBuilder
和XMLMapperBuilder
是兩個(gè)具體的例子,它們負(fù)責(zé)解析MyBatis的配置文件和映射文件。
實(shí)現(xiàn)原理:這段代碼展示了BaseExecutor
中的query
方法,這是一個(gè)模板方法,它定義了執(zhí)行查詢的基本流程,并將具體的查詢邏輯委托給doQuery
方法。子類需要根據(jù)不同的需求實(shí)現(xiàn)doQuery
方法,比如SimpleExecutor
、ReuseExecutor
等都有各自的實(shí)現(xiàn),這正是模板方法模式的典型應(yīng)用。
public class XMLConfigBuilder extends BaseBuilder {private boolean parsed;private final XPathParser parser;public XMLConfigBuilder(InputStream inputStream) {this(new XPathParser(inputStream, true, null));}public Configuration parse() {if (parsed) {throw new BuilderException("Each XMLConfigBuilder can only be used once.");}parsed = true;// 省略解析過程...return configuration;}
}
策略模式 - Strategy Pattern
MyBatis的緩存策略使用了策略模式。MyBatis允許用戶選擇或自定義緩存實(shí)現(xiàn),這是通過將緩存行為抽象成接口,并允許動(dòng)態(tài)設(shè)置具體實(shí)現(xiàn)來實(shí)現(xiàn)的。
實(shí)現(xiàn)原理:Cache
接口定義了緩存的行為,而PerpetualCache
提供了Cache
接口的一個(gè)基礎(chǔ)實(shí)現(xiàn)。MyBatis還支持更多緩存實(shí)現(xiàn),如OSCache、Ehcache等,開發(fā)人員可以根據(jù)需要選擇或自定義緩存策略,這體現(xiàn)了策略模式的靈活性。
public interface Cache {void putObject(Object key, Object value);Object getObject(Object key);// 更多方法...
}public class PerpetualCache implements Cache {private Map<Object, Object> cache = new HashMap<>();@Overridepublic void putObject(Object key, Object value) {cache.put(key, value);}@Overridepublic Object getObject(Object key) {return cache.get(key);}// 實(shí)現(xiàn)其他方法...
}
觀察者模式 - Observer Pattern
MyBatis利用觀察者模式來實(shí)現(xiàn)插件功能。插件可以在MyBatis操作數(shù)據(jù)庫的關(guān)鍵節(jié)點(diǎn)被插入,比如執(zhí)行查詢之前。這種機(jī)制使得用戶能夠在不修改MyBatis核心代碼的情況下,擴(kuò)展其功能。
實(shí)現(xiàn)原理:Interceptor
接口定義了插件需要實(shí)現(xiàn)的intercept
方法。SomePlugin
是一個(gè)具體的插件實(shí)現(xiàn),它可以在方法調(diào)用前后執(zhí)行額外的邏輯。這種方式使得MyBatis能夠在運(yùn)行時(shí)靈活地?cái)U(kuò)展功能,體現(xiàn)了觀察者模式的特點(diǎn)。
public interface Interceptor {Object intercept(Invocation invocation) throws Throwable;// 更多方法...
}public class SomePlugin implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {// 在執(zhí)行前后添加額外的操作Object returnObject = invocation.proceed();// 在執(zhí)行后處理return returnObject;}
}
三、MyBatis源碼解析
深入探討MyBatis的源碼對(duì)于理解其設(shè)計(jì)模式的應(yīng)用至關(guān)重要。由于篇幅限制,我們將通過幾個(gè)關(guān)鍵組件的源碼片段來揭示MyBatis是如何實(shí)現(xiàn)上文提到的設(shè)計(jì)模式的。請(qǐng)注意,下面的代碼是簡化版本,旨在幫助理解其核心原理。
工廠模式 -?SqlSessionFactoryBuilder
MyBatis通過SqlSessionFactoryBuilder
創(chuàng)建SqlSessionFactory
的過程是工廠模式的一個(gè)典型應(yīng)用。
public class SqlSessionFactoryBuilder {public SqlSessionFactory build(Reader reader) {// 解析配置文件,構(gòu)建Configuration對(duì)象XMLConfigBuilder parser = new XMLConfigBuilder(reader);Configuration config = parser.parse();// 返回SqlSessionFactory實(shí)例return new DefaultSqlSessionFactory(config);}
}
單例模式 -?SqlSessionFactory
雖然MyBatis不直接提供SqlSessionFactory
的單例實(shí)現(xiàn),但在實(shí)際應(yīng)用中,開發(fā)者通常會(huì)將其實(shí)現(xiàn)為單例模式,以下是一個(gè)簡單的示例:
public class MyBatisUtil {private static SqlSessionFactory sqlSessionFactory;static {InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);}public static SqlSessionFactory getSqlSessionFactory() {return sqlSessionFactory;}
}
代理模式 -?MapperProxyFactory
MyBatis使用JDK動(dòng)態(tài)代理為Mapper接口生成代理對(duì)象,以便攔截接口方法的調(diào)用。
public class MapperProxy<T> implements InvocationHandler {private final SqlSession sqlSession;private final Class<T> mapperInterface;public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface) {this.sqlSession = sqlSession;this.mapperInterface = mapperInterface;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 省略具體實(shí)現(xiàn)return sqlSession.selectList(mapperInterface.getCanonicalName() + "." + method.getName());}
}public class MapperProxyFactory<T> {private final Class<T> mapperInterface;public MapperProxyFactory(Class<T> mapperInterface) {this.mapperInterface = mapperInterface;}public T newInstance(SqlSession sqlSession) {MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface);return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, mapperProxy);}
}
總結(jié)
每個(gè)設(shè)計(jì)模式的實(shí)現(xiàn)都體現(xiàn)了MyBatis設(shè)計(jì)的巧妙和優(yōu)雅,通過這些模式的應(yīng)用,MyBatis成功地將框架的靈活性、可擴(kuò)展性和維護(hù)性提升到了一個(gè)新的高度。希望通過這三部分的解析,你能對(duì)MyBatis的設(shè)計(jì)和實(shí)現(xiàn)有一個(gè)更加深入的理解。
?如果本文對(duì)你有幫助 歡迎 關(guān)注?、點(diǎn)贊?、收藏?、評(píng)論,?博主才有動(dòng)力持續(xù)創(chuàng)作!!!
?博主v:XiaoMing_Java
??📫作者簡介:嗨,大家好,我是??小明?,互聯(lián)網(wǎng)大廠后端研發(fā)專家,2022博客之星TOP3 / 博客專家 / CSDN后端內(nèi)容合伙人、InfoQ(極客時(shí)間)簽約作者、阿里云簽約博主、全網(wǎng) 6 萬粉絲博主。
🍅 文末獲取聯(lián)系 🍅??👇🏻 精彩專欄推薦訂閱收藏 👇🏻
專欄系列(點(diǎn)擊解鎖)
學(xué)習(xí)路線(點(diǎn)擊解鎖)
知識(shí)定位
🔥Redis從入門到精通與實(shí)戰(zhàn)🔥
Redis從入門到精通與實(shí)戰(zhàn)
圍繞原理源碼講解Redis面試知識(shí)點(diǎn)與實(shí)戰(zhàn)
🔥MySQL從入門到精通🔥
MySQL從入門到精通
全面講解MySQL知識(shí)與企業(yè)級(jí)MySQL實(shí)戰(zhàn) 🔥計(jì)算機(jī)底層原理🔥
深入理解計(jì)算機(jī)系統(tǒng)CSAPP
以深入理解計(jì)算機(jī)系統(tǒng)為基石,構(gòu)件計(jì)算機(jī)體系和計(jì)算機(jī)思維
Linux內(nèi)核源碼解析
圍繞Linux內(nèi)核講解計(jì)算機(jī)底層原理與并發(fā)
🔥數(shù)據(jù)結(jié)構(gòu)與企業(yè)題庫精講🔥
數(shù)據(jù)結(jié)構(gòu)與企業(yè)題庫精講
結(jié)合工作經(jīng)驗(yàn)深入淺出,適合各層次,筆試面試算法題精講
🔥互聯(lián)網(wǎng)架構(gòu)分析與實(shí)戰(zhàn)🔥
企業(yè)系統(tǒng)架構(gòu)分析實(shí)踐與落地
行業(yè)最前沿視角,專注于技術(shù)架構(gòu)升級(jí)路線、架構(gòu)實(shí)踐
互聯(lián)網(wǎng)企業(yè)防資損實(shí)踐
互聯(lián)網(wǎng)金融公司的防資損方法論、代碼與實(shí)踐
🔥Java全棧白寶書🔥
精通Java8與函數(shù)式編程
本專欄以實(shí)戰(zhàn)為基礎(chǔ),逐步深入Java8以及未來的編程模式
深入理解JVM
詳細(xì)介紹內(nèi)存區(qū)域、字節(jié)碼、方法底層,類加載和GC等知識(shí)
深入理解高并發(fā)編程
深入Liunx內(nèi)核、匯編、C++全方位理解并發(fā)編程
Spring源碼分析
Spring核心七IOC/AOP等源碼分析
MyBatis源碼分析
MyBatis核心源碼分析
Java核心技術(shù)
只講Java核心技術(shù)