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