返回
mybatis 插件及动态代理,不仅仅局限于 Mybatis
闲谈
2024-01-20 15:31:23
众所周知,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 的插件和动态代理机制应用到更广泛的场景中,从而提升代码的灵活性、可扩展性和可维护性。