插件机制示例代码
package interceptor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MybatisPluginDemo {
interface Executor {
Object query(String sql);
}
static class SimpleExecutor implements Executor {
@Override
public Object query(String sql) {
System.out.println("【执行SQL】: " + sql);
return "查询结果: " + sql;
}
}
interface Interceptor {
Object intercept(Invocation invocation) throws Throwable;
default Object plugin(Object target) {
return Plugin.wrap(target, this);
}
}
static 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 proceed() throws Throwable {
return method.invoke(target, args);
}
}
static class Plugin implements InvocationHandler {
private final Object target;
private final Interceptor interceptor;
private Plugin(Object target, Interceptor interceptor) {
this.target = target;
this.interceptor = interceptor;
}
public static Object wrap(Object target, Interceptor interceptor) {
Class<?> type = target.getClass();
Class<?>[] interfaces = type.getInterfaces();
if (interfaces.length > 0) {
return Proxy.newProxyInstance(
type.getClassLoader(),
interfaces,
new Plugin(target, interceptor)
);
}
return target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return interceptor.intercept(new Invocation(target, method, args));
}
}
static class LogInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
System.out.println("【日志拦截器】>>> 开始执行: " + invocation.method.getName() +
", 参数: " + Arrays.toString(invocation.args));
Object result = invocation.proceed();
System.out.println("【日志拦截器】<<< 执行完成,结果: " + result);
return result;
}
}
static class PerformanceInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
long start = System.currentTimeMillis();
System.out.println("【性能拦截器】开始计时...");
Object result = invocation.proceed();
long duration = System.currentTimeMillis() - start;
System.out.println("【性能拦截器】执行耗时: " + duration + "ms");
return result;
}
}
static class SqlFormatInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
if ("query".equals(invocation.method.getName())) {
String sql = (String) invocation.args[0];
String formattedSql = sql.replaceAll("\\s+", " ").trim();
System.out.println("【SQL美化拦截器】原始SQL: " + sql);
System.out.println("【SQL美化拦截器】美化后SQL: " + formattedSql);
invocation.args[0] = formattedSql;
}
return invocation.proceed();
}
}
public static void main(String[] args) {
Executor target = new SimpleExecutor();
List<Interceptor> interceptors = new ArrayList<>();
interceptors.add(new LogInterceptor());
interceptors.add(new PerformanceInterceptor());
interceptors.add(new SqlFormatInterceptor());
System.out.println("开始创建多层代理...");
for (Interceptor interceptor : interceptors) {
target = (Executor) interceptor.plugin(target);
System.out.println("添加拦截器: " + interceptor.getClass().getSimpleName());
}
System.out.println("\n代理对象类型: " + target.getClass().getName());
System.out.println("\n执行查询操作:");
Object result = target.query(" SELECT * FROM users WHERE id = 1 ");
System.out.println("\n最终结果: " + result);
}
}
- JDK动态代理创建的代理对象为Proxy类型
- 每个Proxy类型的代理对象都会关联一个InvocationHandler实现
- 调用代理对象的任何方法都会被转发其关联的InvocationHandler方法中。
- 而插件的InvocationHandler实际上是调用的插件对象的interceptor方法。
- interceptor方法中调用proceed方法进而又调用到了 method.invoke(target,args)
method.invoke(target,args) 这一行的关键在于target对象的性质
如果target对象为一个Proxy代理对象,则 method.invoke(target,args)执行时,依然会转发到target这个对象关联的InvocationHandler的invoke方法中,而如果target是一个普通对象,则会执行普通对象的方法。
method.invoke(target,args) 在整个代理链执行的过程中,method和args是不变的,是原始调用中JVM封装好的。