MyBatis 插件(plugins)介紹
1、MyBatis插件
MyBatis允許用戶在已映射語句執行過程中的某一點進行攔截調用。MyBatis使用插件來攔截的方法調用,故此MyBatis插件通常稱為:Mybatis攔截器。默認情況下,MyBatis允許使用插件來攔截的對象包括下面的四個:
- Executor
- ParameterHandler
- ResultSetHandler
- StatementHandler
說明:Mybatis可以對這四個接口中所有的方法進行攔截。
Mybatis攔截器只能攔截四種類型的接口:Executor、StatementHandler、ParameterHandler和ResultSetHandler。這是在Mybatis的Configuration中寫死了的。就是在下面的幾個函數里面生成代理對象實現攔截的:
這四個類中方法的細節可以通過查看每個方法的簽名來發現,或者直接查看 MyBatis 發行包中的源代碼。如果你想做的不僅僅是監控方法的調用,那么你最好相當了解要重寫的方法的行為。因為如果在試圖修改或重寫已有方法的行為的時候,你很可能在破壞 MyBatis 的核心模塊。這些都是更低層的類和方法,所以使用插件的時候要特別當心。
1.1、MyBatis插件(代理類)示例圖
如上圖所示:MyBatis系統最終會將插件包裝成代理類,通過代理類來執行插件里面的功能。
2、MyBatis自定義插件的實現
通過 MyBatis 提供的強大機制,使用插件是非常簡單的,只需實現 Interceptor 接口,並指定想要攔截的方法簽名即可。
Interceptor 接口的定義如下所示:
public interface Interceptor { //攔截器具體實現 Object intercept(Invocation invocation) throws Throwable; //攔截器的代理類 Object plugin(Object target); //添加屬性 void setProperties(Properties properties); }
對於實現自己的Interceptor而言,有兩個很重要的注解:
(1)@Intercepts用於表明當前的對象是一個Interceptor。其值是一個@Signature數組。代碼如下所示:
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Intercepts { Signature[] value(); }
(2)@Signature則表明要攔截的接口、方法以及對應的參數類型。代碼如下所示:
@Retention(RetentionPolicy.RUNTIME) @Target({}) public @interface Signature { Class<?> type(); String method(); Class<?>[] args(); }
下面來看一個自定義的簡單Interceptor,出自MyBatis官方教程:
// ExamplePlugin.java @Intercepts({@Signature( type= Executor.class, method = "update", args = {MappedStatement.class,Object.class})}) public class ExamplePlugin implements Interceptor { private Properties properties = new Properties(); public Object intercept(Invocation invocation) throws Throwable { // implement pre processing if need Object returnObject = invocation.proceed(); // implement post processing if need return returnObject; } public Object plugin(Object target) { return Plugin.wrap(target, this); } public void setProperties(Properties properties) { this.properties = properties; } }
代碼分析:
在上面的源碼中Plugin.wrap(),是當前攔截器(ExamplePlugin)的代理類。MyBatis通過這個代理類來實現攔截的功能。從這里也可以看出來,MyBatis插件和攔截器的關系:插件是攔截器的代理類。
<!-- mybatis-config.xml --> <plugins> <plugin interceptor="org.mybatis.example.ExamplePlugin"> <property name="someProperty" value="100"/> </plugin> </plugins>
Mybatis在注冊自定義的攔截器時,會先把對應攔截器下面的所有property通過Interceptor的setProperties方法注入給對應的攔截器。然后這個插件將會攔截在 Executor 實例中所有的 “update” 方法調用,這里的 Executor 是負責執行低層映射語句的內部對象。
http://www.mybatis.cn/archives/685.html