myBatis实践-插件plugins
前言
概述 知识点
-
官方文档
截图来自http://www.mybatis.org/mybatis-3/zh/configuration.html#plugins
-
理解总结
- 在mybatis中的插件,其本质还是通过代理模式进行实现。
- Mybatis拦截器设计的一个初衷就是为了供用户在某些时候可以实现自己的逻辑而不必去动Mybatis固有的逻辑。打个比方,对于Executor,Mybatis中有几种实现:BatchExecutor、ReuseExecutor、SimpleExecutor和CachingExecutor。这个时候如果你觉得这几种实现对于Executor接口的query方法都不能满足你的要求,那怎么办呢?是要去改源码吗?当然不。我们可以建立一个Mybatis拦截器用于拦截Executor接口的query方法,在拦截之后实现自己的query方法逻辑,之后可以选择是否继续执行原来的query方法。
- Mybatis拦截器设计的一个初衷就是为了供用户在某些时候可以实现自己的逻辑而不必去动Mybatis固有的逻辑。打个比方,对于Executor,Mybatis中有几种实现:BatchExecutor、ReuseExecutor、SimpleExecutor和CachingExecutor。这个时候如果你觉得这几种实现对于Executor接口的query方法都不能满足你的要求,那怎么办呢?是要去改源码吗?当然不。我们可以建立一个Mybatis拦截器用于拦截Executor接口的query方法,在拦截之后实现自己的query方法逻辑,之后可以选择是否继续执行原来的query方法。
实践
MyBatis 允许使用插件来拦截的方法调用包括:
• Executor (update, query, flushStatements, commit, rollback,
getTransaction, close, isClosed)
• ParameterHandler (getParameterObject, setParameters)
• ResultSetHandler (handleResultSets, handleOutputParameters)
• StatementHandler (prepare, parameterize, batch, update, query)
注意;可以通过插件拦截到这四个对象,修改参数等操作:
本文进行Executor #query方法进行拦截
1、实现org.apache.ibatis.plugin.Interceptor
代码如下
package com.learing.mybatis.util;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import java.util.Properties;
/**
* 自定义mybatis插件
*
* @author dsdj
* @version 1.0
* @className MySimpleInterceptor
* @date 2019/4/13 下午4:13
**/
// @Intercepts,是一个@Signature数组。用于表明当前的对象是一个Interceptor,
// @Signature则表明要拦截的接口、方法以及对应的参数类型
@Intercepts({
@Signature(
method="query",
type= Executor.class,
args={MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}
)
})
public class MySimpleInterceptor implements Interceptor {
/**
* intercept方法就是要进行拦截的时候要执行的方法
* @param invocation
* @return
* @throws Throwable
*/
public Object intercept(Invocation invocation) throws Throwable {
System.out.println("====> mybatis plugin 拦截开始....");
System.out.println("====> "+invocation.getMethod().getName());
System.out.println("====> "+invocation.getTarget().getClass().getName());
System.out.println("====> "+invocation.getArgs().toString());
Object proceed = invocation.proceed();
System.out.println(proceed.toString());
System.out.println("====> mybatis plugin 拦截结束....");
return proceed;
}
/**
* plugin方法是拦截器用于封装目标对象的,
* 通过该方法我们可以返回目标对象本身,
* 也可以返回一个它的代理
* 当返回的是代理的时候,调用intercept方法进行拦截
*
* 即:plugin方法中我们可以决定是否要进行拦截进而决定要返回一个什么样的目标对象
* @param target
* @return
*/
public Object plugin(Object target) {
// 通过Mybatis中Plugin类的静态方法wrap(Object target,Interceptor interceptor),
// 可以决定要返回的对象是目标对象还是对应的代理
// 该方法是基于接口实现的代理对象
// 如果被拦截对象所在的类有实现接口,就为当前拦截对象生成一个【$Proxy】,
// 如果被拦截对象所在的类没有指定接口
// 这个对象之后行为就不会被代理操作
return Plugin.wrap(target, this);
}
/**
* setProperties方法是用于在Mybatis配置文件中指定的属性
* @param properties
*/
public void setProperties(Properties properties) {
}
}
2、配置文件添加插件
<plugins>
<plugin interceptor="com.learing.mybatis.util.MySimpleInterceptor"></plugin>
</plugins>
测试
@Test
public void testMyPlugin(){
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.selectAll();
System.out.println();
}
后记
- mybatis的plugin进行拦截的方法只能限制为指定的几个,因此使用mybatis插件拦截实现业务功能可能不太好控制。因为拦截的方法较为底层。
- 本文只是对plugin的使用进行初步的使用,具体的应用场景还不知道,不过学习后可以去查看mybatis分页插件的实现。