這是我參與更文挑戰的第3天,活動詳情查看: 更文挑戰web
通常狀況下,開源框架都會提供插件或其餘形式的拓展點,供開發者自行拓展。這樣的好處是顯而易見的,一是增長了框架的靈活性。二是開發者能夠結合實際需求,對框架進行拓展,使其可以更好的工做。以MyBatis爲例,咱們可基於MyBatis插件機制實現分頁、分表,監控等功能。因爲插件和業務無關,業務也沒法感知插件的存在。所以能夠無感植入插件,在無形中加強功能sql
Mybatis做爲一個應用普遍的優秀的ORM開源框架,這個框架具備強大的靈活性,在四大組件 (Executor、StatementHandler、ParameterHandler、ResultSetHandler)處提供了簡單易用的插件擴展機制。Mybatis對持久層的操做就是藉助於四大核心對象。MyBatis支持用插件對四大核心對象進行攔截,對mybatis來講插件就是攔截器,用來加強核心對象的功能,加強功能本質上是藉助於底層的 動態代理實現的,換句話說,MyBatis中的四大對象都是代理對象markdown
MyBatis所容許攔截的方法以下:mybatis
在四大對象建立的時候app
攔截框架
插件具體是如何攔截並附加額外的功能的呢?以ParameterHandler來講post
public ParameterHandler newParameterHandler(MappedStatement mappedStatement,Object object, BoundSql sql, InterceptorChain interceptorChain){
ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement,object,sql);
parameterHandler = (ParameterHandler)
interceptorChain.pluginAll(parameterHandler);
return parameterHandler;
}
public Object pluginAll(Object target) {
for (Interceptor interceptor : interceptors)
{
target = interceptor.plugin(target);
}
return target;
}
複製代碼
interceptorChain保存了全部的攔截器(interceptors),是mybatis初始化的時候建立的。調用攔截器鏈中的攔截器依次的對目標進行攔截或加強。interceptor.plugin(target)中的target就能夠理解爲mybatis 中的四大對象。返回的target是被重重代理後的對象ui
若是咱們想要攔截Executor的query方法,那麼能夠這樣定義插件:url
@Intercepts({
@Signature(
type = Executor.class,
method = "query",
args={MappedStatement.class,Object.class,RowBounds.class,ResultHandler.class}
)
})
public class ExeunplePlugin implements Interceptor {
//省略邏輯
}
複製代碼
除此以外,咱們還需將插件配置到sqlMapConfig.xml中。spa
<plugins>
<plugin interceptor="com.lagou.plugin.ExamplePlugin"></plugin>
</plugins>
複製代碼
這樣MyBatis在啓動時能夠加載插件,並保存插件實例到相關對象(InterceptorChain,攔截器鏈) 中。待準備工做作完後,MyBatis處於就緒狀態。咱們在執行SQL時,須要先經過DefaultSqlSessionFactory 創 建 SqlSession。Executor 實例會在建立 SqlSession 的過程當中被建立, Executor實例建立完畢後, MyBatis會經過JDK動態代理爲實例生成代理類。這樣,插件邏輯便可在 Executor相關方法被調用前執行。
以上就是MyBatis插件機制的基本原理.
但願對各位小夥伴有所幫助