一針見血MyBatis插件機制
要想一針見血地理解MyBatis插件機制,只需要明白一點:原身和變身。也就是說,一旦配置上插件,ParameterHandler,ResultSetHandler,StatementHandler,Executor這四大核心對象,將會生成變身,是一種代理對象,而不再是原身。
1、MyBatis插件配置
MyBatis框架的配置文件,即mybatis-config.xml文件中,包括了插件的設置。
2、插件的分類
根據功能,可以將插件分為兩大類:
第一類:插件是對系統的一種補充,例如在分布式系統中,可以使用插件的方式,實現內存插件、磁盤插件、線性網絡插件、Paxos插件等。此類插件等同于組件。
第二類:插件是對系統默認功能的自定義修改,例如mybatis里面自定義插件,它實現的攔截器的功能。此類插件等同于攔截器。
3、MyBatis攔截器插件
mybatis里面自定義插件屬于攔截器插件,大凡攔截器都需要關注兩個要點:
(1)攔截的對象是誰,用代碼行話來說,target目標是誰?
(2)攔截的技術方案是什么?
下面,針對這兩個問題進行詳細的闡述一下。
3.1、攔截的對象
我們知道,MyBatis有四大核心對象:
(1)ParameterHandler:處理SQL的參數對象
(2)ResultSetHandler:處理SQL的返回結果集
(3)StatementHandler:數據庫的處理對象,用于執行SQL語句
(4)Executor:MyBatis的執行器,用于執行增刪改查操作
那么,MyBatis攔截器針對的對象就是上面“四大金剛”。
3.2、攔截的技術方案
在Java里面,我們想攔截某個對象,只需要把這個對象包裝一下,用代碼行話來說,就是重新生成一個代理對象。
這樣在每次調用Executor類的方法的時候,總是要經過Interceptor接口的攔截。
3.3、攔截對象的變身
一旦我們在mybatis-config.xml里面配置了插件:
<plugins>
<plugin interceptor="cn.mybatis.MyInterceptor"></plugin>
</plugins>
ParameterHandler,ResultSetHandler,StatementHandler,Executor這“四大金剛”就發生變身,而不再是原身。這個變身的過程是這樣的,以ParameterHandler為例:
第一步:根據插件配置,利用反射技術,創建interceptor攔截器
Interceptor interceptor = (Interceptor) MyInterceptor.class.newInstance();
第一步:創建原身
ParameterHandler parameterHandler = createParameterHandler();
第二步:原身+攔截器---->變身
parameterHandler = (ParameterHandler) Plugin.wrap(parameterHandler, interceptor);
在這一步,將parameterHandler和interceptor包裝到一起,生成了變身,并重新賦值給parameterHandler變量
代碼備注:也許上面的代碼,你沒有看懂,但是沒有關系,其中的細節你可以不去探究,你只要明白代碼的字面意思,createParameterHandler(),這是創建ParameterHandler對象,Plugin.wrap就是包裝,把兩個類包裝一下,重新生成一個新的類。你只要能理清“原身->變身”這個過程,這就足夠了,就能把MyBatis插件機制的精髓已經掌握了。
4、MyBatis攔截器插件整個運行過程
4.1、沒有插件的運行過程
4.2、有插件的運行過程
5、本文小結
大凡提到“MyBatis插件”,很多人感覺這是一個高大上的玩意,深入MyBatis源碼內核,威力巨大,也破壞巨大,讓人萬分小心,惴惴不安。其實不然,添加插件,就是給mybatis核心對象生成了變身而已。也就是說,一旦配置上插件,ParameterHandler,ResultSetHandler,StatementHandler,Executor這四大核心對象,將會生成變身,是一種代理對象,而不再是原身,僅此而已。通過本文的一針見血,希望大家能夠放開手腳,大膽嘗試,開發MyBatis插件不是困難的事情。當然,更多的插件開發細節介紹,敬請關注 mybatis插件 這個系列。