Mybatis 插件之自定义插件

1、前言

简单的说,mybatis插件就是对ParameterHandler、ResultSetHandler、StatementHandler、Executor这四个接口上的方法进行拦截,利用JDK动态代理机制,为这些接口的实现类创建代理对象,在执行方法时,先去执行代理对象的方法,从而执行自己编写的拦截逻辑,所以真正要用好mybatis插件,主要还是要熟悉这四个接口的方法以及这些方法上的参数的含义;

另外,如果配置了多个拦截器的话,会出现层层代理的情况,即代理对象代理了另外一个代理对象,形成一个代理链条,执行的时候,也是层层执行;

关于mybatis插件涉及到的设计模式和软件思想如下:

设计模式:代理模式、责任链模式;
软件思想:AOP编程思想,降低模块间的耦合度,使业务模块更加独立;
一些注意事项:

不要定义过多的插件,代理嵌套过多,执行方法的时候,比较耗性能;
拦截器实现类的intercept方法里最后不要忘了执行invocation.proceed()方法,否则多个拦截器情况下,执行链条会断掉;

2、Springboot 编写 mybatis 插件

编写 mybatis 插件很简单,首先定义要拦截的是上面说到的哪个类,拦截哪个方法,参数是啥,然后配置一下即可

package com.snowflake1.test.config;

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.util.Properties;

@Intercepts({
        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class MyPlugin implements Interceptor {

    private Logger logger = LoggerFactory.getLogger(MyPlugin.class);

    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) {
            logger.info("本次数据库操作是慢查询,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"));
    }
}

在 springboot 那配置一下(我用的是 mybatisplus)

package com.snowflake1.test.config;

import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;

@Configuration
public class MapperConfig {
    //将插件加入到mybatis插件拦截链中
    @Bean
    public ConfigurationCustomizer configurationCustomizer() {
        return new ConfigurationCustomizer() {
            @Override
            public void customize(MybatisConfiguration configuration) {
                //插件拦截链采用了责任链模式,执行顺序和加入连接链的顺序有关
                MyPlugin myPlugin = new MyPlugin();
                //设置参数,比如阈值等,可以在配置文件中配置,这里直接写死便于测试
                Properties properties = new Properties();
                //这里设置慢查询阈值为1毫秒,便于测试
                properties.setProperty("time", "1");
                myPlugin.setProperties(properties);
                configuration.addInterceptor(myPlugin);
            }
        };
    }
}

你可能感兴趣的:(Mybatis 插件之自定义插件)