181. Spring Boot MyBatis自定义Plugin


 

【视频&交流平台】

à SpringBoot视频

http://study.163.com/course/introduction.htm?courseId=1004329008&utm_campaign=commission&utm_source=400000000155061&utm_medium=share

à SpringCloud视频

http://study.163.com/course/introduction.htm?courseId=1004638001&utm_campaign=commission&utm_source=400000000155061&utm_medium=share

à Spring Boot源码

https://gitee.com/happyangellxq520/spring-boot

à Spring Boot交流平台

http://412887952-qq-com.iteye.com/blog/2321532

 

需求缘起:

       在网易云课堂的讨论区(传送门)中有人咨询:老师,PageHelper的实现原理是怎么样的?这个原理吧,当然不是一两句话就能说明白的,所以这里打算撰文说下。

 

本节大纲:

写道
一、自定义插件的思路
二、自定义插件编码:记录SQL

 

 

一、自定义插件的思路

 

1.1 实现接口Interceptor

 

要在mybatis自定义插件的话,那么要实现如下接口:

org.apache.ibatis.plugin.Interceptor

     

  在此接口中主要有三个方法:

 

 

Object intercept(Invocation invocation) throws Throwable;
Object plugin(Object target);
void setProperties(Properties properties);
 

 

       那么这三个都是都能干嘛呢?

 

1)方法plugin(Object target)

plugin方法是拦截器用于封装目标对象的,通过该方法我们可以返回目标对象本身,也可以返回一个它的代理。当返回的是代理的时候我们可以对其中的方法进行拦截来调用intercept方法,当然也可以调用其他方法。

 

2)方法setProperties(Properties properties)

setProperties方法是用于在Mybatis配置文件中指定一些属性的。

 

3)方法intercept(Invocation invocation)

定义自己的Interceptor最重要的是要实现plugin方法和intercept方法,在plugin方法中我们可以决定是否要进行拦截进而决定要返回一个什么样的目标对象。而intercept方法就是要进行拦截的时候要执行的方法。

 

 1.2 使用@Bean注入自定义的Plugin

       spring boot中可以使用如下代码进行注入:

 

@Bean
    public SQLStatsInterceptor sqlStatsInterceptor(){
        SQLStatsInterceptor sqlStatsInterceptor = new SQLStatsInterceptor();
        Properties properties = new Properties();
        properties.setProperty("dialect", "mysql");
         sqlStatsInterceptor.setProperties(properties);
       return sqlStatsInterceptor;
}
 

       如果是在spring中使用xml配置的方式的话,可以使用如下的方式进行注入:

<configuration>
    <plugins>
        <plugin interceptor="com.kfit.config.interceptor.SQLStatsInterceptor">
            <property name="dialect" value="mysql" />
        </plugin>
    </plugins>
</configuration>
 

 

 

 

1.3 思路总结

       上面那多废话,简单来说就是:其一需要定义实现接口Interceptor;其二就是要配置注入。千言万语, 不如一句代码,还是写个例子看看效果吧。

                             

二、自定义插件编码:记录SQL

 

2.1 需求描述

       在这里实现:把Mybatis所有执行的sql都记录下来。

 

2.2 代码实现分析

通过对 MyBatis org.apache.ibatis.executor.statement.StatementHandler中的prepare 方法进行拦截即可。

 

 

2.3 代码实现

2.3.1实现类SQLStatsInterceptor实现接口Interceptor

package com.kfit.config.interceptor;
import java.sql.Connection;
import java.util.Properties;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
 
@Intercepts({@Signature(type=StatementHandler.class,method="prepare",args={Connection.class,Integer.class})})
public class SQLStatsInterceptor implements Interceptor {
 
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
       StatementHandler statementHandler= (StatementHandler) invocation.getTarget();
       BoundSql boundSql = statementHandler.getBoundSql();
       System.out.println(boundSql.getSql());
       return invocation.proceed();
    }
 
    @Override
    public Object plugin(Object target) {
       return Plugin.wrap(target, this);
    }
 
    @Override
    public void setProperties(Properties properties) {
        String dialect = properties.getProperty("dialect");
        System.out.println("dialect="+dialect);
    }
}

 

代码分析:

1)首先SQLStatsInterceptor类实现了接口Interceptor

2)需要重写3个方法,核心的拦截处理方法是intercept,在这个方法中可以获取到对应的绑定的sql,在这里作为演示只是打印了SQL,如果需要可以保存起来。

3)在方法上有一个很重要的注解@Intercepts,在此注解上配置的注解说明了要拦截的类(type=StatementHandler.class),拦截的方法(method="prepare"),方法中的参数(args={Connection.class,Integer.class}),也就是此拦截器会拦截StatementHandler类中的如下方法:

 

Statement prepare(Connection connection, Integer transactionTimeout)

  

      

 

这里顺带提一下,可以拦截的类:

StatementHandler (prepare, parameterize, batch, update, query)

ResultSetHandler (handleResultSets, handleOutputParameters)

ParameterHandler (getParameterObject, setParameters)

Executor (update, query, flushStatements, commit, rollback,getTransaction, close, isClosed)

 

 

2.3.2定义配置类进行注入

@Configuration
public class MyBatisConfiguration {
    @Bean
    public SQLStatsInterceptor sqlStatsInterceptor(){
        SQLStatsInterceptor sqlStatsInterceptor = new SQLStatsInterceptor();
        Properties properties = new Properties();
        properties.setProperty("dialect", "mysql");
         sqlStatsInterceptor.setProperties(properties);
       return sqlStatsInterceptor;
    }
}

 

       到这里就可以测试使用了。一旦懂了自定义Plugin后,那么对于PageHelper的实现也就明白了七八分了。

 

猜你喜欢

转载自412887952-qq-com.iteye.com/blog/2409334