很多在service上的逻辑,可以由Mybatis在DAO层实现,比如说:
- 分页,比较有名气的PageHelper
- 对数据加密/解密
而想要在Mybatis上实现此类功能,则需要有Mybatis PLugin的帮助。
其主要思想是,在已映射了的statement上,进行拦截,替换/增强新的逻辑。
Mybatis允许对如下的方法进行拦截:
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
想要对以上的statement/method进行拦截,需要借助Interceptor
来实现…
看下Interceptor
接口
public interface Interceptor {
//主要实现这个方法,实现拦截的逻辑;可以看到参数为Invocation,由此可以获取到所要拦截对象的信息
Object intercept(Invocation invocation) throws Throwable;
//这一步生成代理对象,看下Plugin.wrap这个方法的话,Proxy.newProxyInstance,所以这是个JDK的dynamic proxy
default Object plugin(Object target) {
return Plugin.wrap(target, this);
}
//传递参数的
default void setProperties(Properties properties) {}
}
看个Plugin
的实例:
//这是一个想要拦截Executor.update()方法的plugin,这里的参数,可以从Executor.update()方法的源码处获取
@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 {
// enhancement
Object returnObject = invocation.proceed();
// enhancement
return returnObject;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
}
写好了的Plugin如何effect?
org.apache.ibatis.session.Configuration.addInterceptor(Intercept)
那么上面这个方法是如何将我们实现的Plugin添加到Mybatis的工作流程中的呢?如果感兴趣的话,可以看下我的另一篇介绍设计模式-责任链模式
的blog