返回

mybatis 插件及动态代理,不仅仅局限于 Mybatis

闲谈

众所周知,mybatis 是一个优秀的 ORM 框架,它的插件机制和动态代理在很多场景下都发挥着重要的作用。然而,你可能不知道,这些机制并不局限于 mybatis 框架本身,而是可以单独拿出来使用,从而拓展其应用范围。

一、mybatis 的插件

mybatis 的插件使用拦截器链的方式进行调用。通过实现 org.apache.ibatis.plugin.Interceptor 接口,我们可以自定义自己的插件,并拦截特定方法的调用。例如,我们可以拦截 org.apache.ibatis.executor.Executor 接口的 query 方法,从而在查询执行前后做一些额外的处理。

public class MyPlugin implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 在查询执行前做一些额外的处理
        System.out.println("查询前:" + invocation.getMethod().getName());

        // 调用原方法执行查询
        Object result = invocation.proceed();

        // 在查询执行后做一些额外的处理
        System.out.println("查询后:" + invocation.getMethod().getName());

        return result;
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        // 可以在这里获取配置信息
    }
}

二、动态代理

除了拦截器链的方式,mybatis 还提供了动态代理的方式来调用插件。通过实现 org.apache.ibatis.plugin.InvocationHandler 接口,我们可以自定义自己的代理类,并代理特定接口或类的调用。例如,我们可以代理 org.apache.ibatis.executor.Executor 接口,从而在查询执行前后做一些额外的处理。

public class MyInvocationHandler implements InvocationHandler {

    private Executor executor;

    public MyInvocationHandler(Executor executor) {
        this.executor = executor;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在查询执行前做一些额外的处理
        System.out.println("查询前:" + method.getName());

        // 调用原方法执行查询
        Object result = method.invoke(executor, args);

        // 在查询执行后做一些额外的处理
        System.out.println("查询后:" + method.getName());

        return result;
    }
}

三、脱离 mybatis 框架使用

mybatis 的插件和动态代理机制并不局限于 mybatis 框架本身,我们可以将其单独拿出来使用,从而拓展其应用范围。例如,我们可以使用 mybatis 的插件去拦截 HashMap 的 get 方法,从而在获取值之前做一些额外的处理。

import java.util.HashMap;
import java.util.Map;

import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;

public class MyHashMapPlugin implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 在获取值之前做一些额外的处理
        System.out.println("获取值前:" + invocation.getMethod().getName());

        // 调用原方法获取值
        Object result = invocation.proceed();

        // 在获取值后做一些额外的处理
        System.out.println("获取值后:" + invocation.getMethod().getName());

        return result;
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        // 可以在这里获取配置信息
    }

    public static void main(String[] args) {
        // 创建一个 HashMap
        Map<String, Object> map = new HashMap<>();
        map.put("key1", "value1");

        // 拦截 HashMap 的 get 方法
        MyHashMapPlugin plugin = new MyHashMapPlugin();
        Map<String, Object> proxyMap = (Map<String, Object>) Plugin.wrap(map, plugin);

        // 获取值
        Object value = proxyMap.get("key1");

        // 输出结果
        System.out.println("获取的值:" + value);
    }
}

通过这种方式,我们可以将 mybatis 的插件和动态代理机制应用到更广泛的场景中,从而提升代码的灵活性、可扩展性和可维护性。