美文网首页
Mybatis 插件之自定义插件

Mybatis 插件之自定义插件

作者: 放开那个BUG | 来源:发表于2021-01-22 22:09 被阅读0次

    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 插件之自定义插件

          本文链接:https://www.haomeiwen.com/subject/kkjszktx.html