MyBatis Interceptor


MyBatis的攔截器可以用於在以下對象及方法中攔截修改:

  • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  • ParameterHandler (getParameterObject, setParameters)
  • ResultSetHandler (handleResultSets, handleOutputParameters)
  • StatementHandler (prepare, parameterize, batch, update, query)

每一個方法會對應不同的參數列表, 這些需要體現在Intercepts的Signature中

配置

除了實現Interceptor接口以外, 需要在項目中做以下配置

application.yml

增加對應的mybatis-config.xml, 因為現在還不支持在yml中配置plugin

mybatis:
  type-aliases-package: com.compayn.proj.commons.api.dto
  mapper-locations: classpath:mapper/*.xml
  config-location: classpath:mybatis-config.xml

mybatis-config.xml

增加mybatis配置文件, 注意這里配置的攔截器, 其實際執行順序是自下而上的

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <settings>
        <setting name="..." value="true" />
    </settings>

    <plugins>
        <!-- The invocation order is bottom up -->
        <plugin interceptor="com.company.proj.commons.impl.interceptor.BaseInterceptor" />
    </plugins>

</configuration>

  

Interceptor實現

一個簡單的攔截器實現, 可以輸出執行的sql, 以及執行時間.

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
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;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Statement;
import java.util.Properties;

@Intercepts({
        @Signature(type = StatementHandler.class, method = "batch", args = { Statement.class}),
        @Signature(type = StatementHandler.class, method = "update", args = { Statement.class}),
        @Signature(type = StatementHandler.class, method = "query", args = { Statement.class, ResultHandler.class}),
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class,Object.class})})
public class BaseInterceptor implements Interceptor {
    private static Logger logger = LoggerFactory.getLogger(BaseInterceptor.class);

    /**
     * 用於封裝目標對象, 可以返回目標對象本身也可以返回一個它的代理, 這將決定是否會進行攔截
     */
    @Override
    public Object plugin(Object target) {
        if (target instanceof Executor) { // 僅當對象為Executor時, 才使用本插件
            return Plugin.wrap(target, this);
        } else {
            return target;
        }
    }

    /**
     * 用於配置本插件的相關屬性
     */
    @Override
    public void setProperties(Properties properties) {
        // Do nothing
    }

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        long start = System.currentTimeMillis();

        Object target = invocation.getTarget(); //被代理對象

        if (target instanceof Executor) {
            MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
            Object parameter = invocation.getArgs()[1];
            BoundSql boundSql = mappedStatement.getBoundSql(parameter);
            String sql = boundSql.getSql();
            logger.info("SQL: {}", sql);
        }

        Object result = invocation.proceed();
        long duration = System.currentTimeMillis() - start;
        logger.info("Time elapsed: {}ms", duration);
        return result;
    }
}

代碼說明

@Intercepts 注解: 這個地方配置需要攔截的對象方法, 每個方法對應一個Signature, 這個Signature由對象類型, 方法名和參數組成, 方法名和參數可以直接參考這個對象的接口.

Object plugin(Object target)接口: 用於封裝目標對象, 可以返回目標對象本身也可以返回一個它的代理, 這將決定是否會進行攔截

void setProperties(Properties properties)接口: 用於配置本插件的相關屬性, 值可以通過Mybatis配置文件傳入

Object intercept(Invocation invocation) throws Throwable接口: 執行攔截的方法, 其中 invocation.getTarget() 可以看到實際被代理的對象, 根據對象類型不同, 可以讀取這個對象方法的參數並進行需要的操作.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM