什么是mybatis插件
mybatis插件就是在执行数据库操作的时候,对于特定方法进行拦截增强,做一些额外的处理的一种方式。
myabtis的插件的增强原理是利用动态代理实现的,可以对数据库操作的执行类做拦截,mybatis中的几个操作数据库的执行类是:
Executor
StatementHandler
ParameterHandler
ResultSetHandler
其中:
Executor 是总的执行者,他就像一个大总管,用于协调管理其他执行者。
StatementHandler 是用于生成Statement或者PreparedStatement的执行者,同时他会调用ParameterHandler进行对sql语句中的参数设值,设值完了之后会通过StatementHandler 去调用sql在数据库中执行,最后返回一个结果集,通过ResultSetHandler将结果集和对应的实体进行映射填充数据,之后会把结果实体返回给StatementHandler。
所以,我们对这几个执行者进行拦截,比如对于StatementHandler 拦截,即是对于sql操作进行拦截,下面就对于这个StatementHandler 进行拦截做一个实例。
实例
需求
拦截所以数据库sql执行时长超过1毫秒的方法,并记录sql。
实现
插件类
@Intercepts({
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class MyPlugin implements Interceptor {
private long time;
//方法拦截
@Override
public Object intercept(Invocation invocation) throws Throwable {
//通过StatementHandler获取执行的sql
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
BoundSql boundSql = statementHandler.getBoundSql();
String sql = boundSql.getSql();
long start = System.currentTimeMillis();
Object proceed = invocation.proceed();
long end = System.currentTimeMillis();
if ((end - start) > time) {
System.out.println("本次数据库操作是慢查询,sql是:" + sql);
}
return proceed;
}
//获取到拦截的对象,底层也是通过代理实现的,实际上是拿到一个目标代理对象
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
//获取设置的阈值等参数
@Override
public void setProperties(Properties properties) {
this.time = Long.parseLong(properties.getProperty("time"));
}
}
myabtis自定义插件只需要实现Interceptor接口即可,并且注解@Intercepts以及@Signature配置需要拦截的对象,其中type是需要拦截的对象Class,method是对象里面的方法,args是方法参数类型。
注入插件到拦截链
这里有两种方式注入
方式一:直接注入
@org.springframework.context.annotation.Configuration
@MapperScan({"com.springboot.demo.mapper"})
public class MapperConfig {
//注册插件
@Bean
public MyPlugin myPlugin() {
MyPlugin myPlugin = new MyPlugin();
//设置参数,比如阈值等,可以在配置文件中配置,这里直接写死便于测试
Properties properties = new Properties();
//这里设置慢查询阈值为1毫秒,便于测试
properties.setProperty("time", "1");
myPlugin.setProperties(properties);
return myPlugin;
}
}
方式二:通过myabtis配置加入到拦截链中
@org.springframework.context.annotation.Configuration
@MapperScan({"com.springboot.demo.mapper"})
public class MapperConfig {
//将插件加入到mybatis插件拦截链中
@Bean
public ConfigurationCustomizer configurationCustomizer() {
return new ConfigurationCustomizer() {
@Override
public void customize(Configuration configuration) {
//插件拦截链采用了责任链模式,执行顺序和加入连接链的顺序有关
MyPlugin myPlugin = new MyPlugin();
//设置参数,比如阈值等,可以在配置文件中配置,这里直接写死便于测试
Properties properties = new Properties();
//这里设置慢查询阈值为1毫秒,便于测试
properties.setProperty("time", "1");
myPlugin.setProperties(properties);
configuration.addInterceptor(myPlugin);
}
};
}
}