栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

MyBatis的插件开发

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

MyBatis的插件开发

MyBatis的插件运行原理

MyBatis插件的运行是基于JDK动态代理 + 拦截器链实现。

MyBatis的拦截器可以拦截4大对象,开发者通过自定义拦截器,拦截对应的方法实现插件。

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

在MyBatis的全局配置类Configuration中,定义了一个拦截器链。InterceptorChain中用一个List集合保存所有的拦截器,其中pluginAll方法会遍历List集合,并调用所有拦截器的plugin方法。

public class InterceptorChain {
    // 定义了一个List集合装拦截器对象
    private final List interceptors = new ArrayList();

    public InterceptorChain() {
    }

    // 遍历interceptors,并调用拦截器的plugin方法
    public Object pluginAll(Object target) {
        Interceptor interceptor;
        for(Iterator var2 = this.interceptors.iterator(); var2.hasNext(); target = interceptor.plugin(target)) {
            interceptor = (Interceptor)var2.next();
        }

        return target;
    }

    // 添加拦截器
    public void addInterceptor(Interceptor interceptor) {
        this.interceptors.add(interceptor);
    }

    // 获取interceptors
    public List getInterceptors() {
        return Collections.unmodifiableList(this.interceptors);
    }
}

MyBatis的拦截器,自定义插件就需要实现该接口

public interface Interceptor {
    // 拦截处理
    Object intercept(Invocation var1) throws Throwable;

    // 生成代理对象
    default Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    // 插件的属性设置
    default void setProperties(Properties properties) {
    }
}
public class Invocation {
    // 目标对象
    private final Object target;
    // 目标对象的方法
    private final Method method;
    // 目标对象的方法参数
    private final Object[] args;

    public Invocation(Object target, Method method, Object[] args) {
        this.target = target;
        this.method = method;
        this.args = args;
    }

    public Object getTarget() {
        return this.target;
    }

    public Method getMethod() {
        return this.method;
    }

    public Object[] getArgs() {
        return this.args;
    }

    // 继续往下执行
    public Object proceed() throws InvocationTargetException, IllegalAccessException {
        return this.method.invoke(this.target, this.args);
    }
}

MyBatis插件的开发

第一步:实现 Interceptor接口

package com.learn.blog.demo;

import org.apache.ibatis.executor.Executor;
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.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.lang.reflect.Field;
import java.util.Properties;


@Intercepts({
        @Signature(
                type = Executor.class,
                method = "query",
                args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
public class MyBatisPlugin implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 方法的参数
        Object[] args = invocation.getArgs();
        MappedStatement mappedStatement = (MappedStatement) args[0];
        Object parameterObject = args[1];
        BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);
        // 获取到原查询sql语句
        String sql = boundSql.getSql();
        
        // 利用反射修改boundSql的字段
        Field field = boundSql.getClass().getDeclaredField("sql");
        field.setAccessible(true);
        field.set(boundSql, sql + "limit 1");

        // 修改完继续执行
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Interceptor.super.plugin(target);
    }


    @Override
    public void setProperties(Properties properties) {
        Interceptor.super.setProperties(properties);
    }
}

第二步:在MyBatis中注册拦截器mybatis-config.xml


	
        <--可以指定插件的参数-->
		
		
	

第三步:spring配置中指定Mybatis配置文件路径 

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/988847.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号