8.1、Mybatis插件开发——拦截器

8.1、Mybatis插件开发——拦截器

MyBatis允许在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis可以拦截一下4个接口中的几个方法(括号内为该接口的方法名)。

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

ParameterHandler(getParameterObject、setParameters)

ResultSetHandler(handleResultSets、handleCursorResultSets、handleOutputParameters)

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

这些都是比较底层的类和方法,修改得不好,可能会影响代码执行。所以拦截调用前一定要充分理解。

一、拦截器接口

MyBatis插件通过实现拦截器接口Interceptor(org.apache.ibatis.plugin.Interceptor),即可在实现类中对拦截对象和方法进行处理。

拦截器接口Interceptor:

public interface Interceptor {
  Object intercept(Invocation invocation) throws Throwable;
  Object plugin(Object target);
  void setProperties(Properties properties);
}

1、setProperties

2、plugin

3、intercept

二、拦截器签名

通过拦截器注解,来表明这个拦截器需要拦截的接口和方法

@Intercepts(org.apache.ibatis.plugin.Intercepts)和@Signature(org.apache.ibatis.plugin.Signature)

@Intercepts注解中的属性是一个@Signature(签名)数组,可以在同一个拦截器中同时拦截不同的接口和方法。

@Signature注解包含以下三个属性。

  type:设置拦截的接口,可选值是前面提到的4个接口。

  method:设置拦截接口中的方法名,可选值是前面4个接口对应的方法,需要和接口匹配。

  args:设置拦截方法的参数类型数组,通过方法名和参数类型可以确定唯一一个方法。

0、签名的写法

type:接口类

method:方法名称

args:要拦截的方法的参数类

下面例子为Executor的update方法的签名写法

@Intercepts(
        @org.apache.ibatis.plugin.Signature(
                type = Executor.class, 
                method = "update", 
                args = { MappedStatement.class,Object.class }))
public class ResultSetInterceptor implements Interceptor {

1、Executor接口

int update(MappedStatement ms,Object parameter) throws SQLException

该方法会在所有的 INSERT 、 UPDATE 、 DELETE  执行时被调用,因此如果想要拦截这 3 类操作,可以拦截该方法

<E>List<E>query(MappedStatementms,Objectparameter,RowBoundsrowBounds,ResultHandlerresultHandler)throwsSQLException

该方法会在所有SELECT查询方法执行时被调用。通过这个接口参数可以获取很多有用的信息,因此这是最常被拦截的一个方法。使用该方法需要注意的是,虽然接口中还有一个参数更多的同名接口,但由于MyBatis的设计原因,这个参数多的接口不能被拦截

<E> Cursor <E> queryCursor(MappedStatement ms,Object parameter,RowBounds rowBounds) throws SQLException

该方法只有在查询的返回值类型为 Cursor 时被调用。

List <BatchResult > flushStatements() throws SQLException

该方法只在通过 SqlSession 方法调用 flushStatements 方法或执行的接口方法中带有 @Flush 注解时才被调用,

void commit(boolean required) throws SQLException

该方法只在通过 SqlSession 方法调用 commit 方法时才被调用,

void rollback(boolean required) throws SQLException

该方法只在通过 SqlSession 方法调用 rollback 方法时才被调用,

Transaction getTransaction()

该方法只在通过 SqlSession 方法获取数据库连接时才被调用,

void close(boolean forceRollback)

该方法只在延迟加载获取新的 Executor 后才会被执行,

boolean isClosed()

该方法只在延迟加载执行查询方法前被执行,

2、ParameterHandler 接口

Object getParameterObject()

该方法只在执行存储过程处理出参的时候被调用。

void setParameters(PreparedStatement ps) throws SQLException

该方法在所有数据库方法设置 SQL 参数时被调用。

3、ResultSetHandler接口

<E> List <E> handleResultSets(Statement stmt) throws SQLException

该方法会在除存储过程及返回值类型为Cursor<T>(org.apache.ibatis.cursor.Cursor<T>)以外的查询方法中被调用。

<E> Cursor <E> handleCursorResultSets(Statement stmt) throws SQLException;

该方法是 3.4.0 版本中新增加的,只会在返回值类型为 Cursor <T>的查询方法中被调用

void handleOutputParameters(CallableStatement cs) throws SQLException;

该方法只在使用存储过程处理出参时被调用,ResultSetHandler接口的第一个方法对于拦截处理MyBatis的查询结果非常有用,并且由于这个接口被调用的位置在处理二级缓存之前,因此通过这种方式处理的结果可以执行二级缓存。

4、StatementHandler接口

Statement prepare(Connection connection,Integer transactionTimeout) throws SQLException

该方法会在数据库执行前被调用,优先于当前接口中的其他方法而被执行

void parameterize(Statement statement) throws SQLException

该方法在prepare方法之后执行,用于处理参数信息

int batch(Statement statement) throws SQLException

在全局设置配置defaultExecutorType="BATCH"时,执行数据操作才会调用该方法

<E> List <E> query(Statement statement,ResultHandler resultHandler) throws SQLException

执行SELECT方法时调用

<E> Cursor <E> queryCursor(Statement statement) throws SQLException

该方法是 3.4.0 版本中新增加的,只会在返回值类型为Cursor<T>的查询中被调用

 三、补充,Spring Boot下使用拦截器 

Spring Boot下需要加入依赖

<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <source>${java.version}</source>
        <target>${java.version}</target>
    </configuration>
</plugin>

 

posted @ 2018-03-10 14:40  LiveYourLife  阅读(421)  评论(0)    收藏  举报