java中拦截器内部实际上是通过jdk动态代理实现的
拦截器一般至少有三个方法:before, around, after,用来处理拦截方法的前后逻辑,具体逻辑图如下:
1. 定义拦截器:
/** * 定义拦截器接口 */ public interface Interceptor { public boolean before(Object proxy, Object target, Method method, Object[] args); public void around(Object proxy, Object target, Method method, Object[] args); public void after(Object proxy, Object target, Method method, Object[] args); } public class MyInterceptor implements Interceptor { @Override public boolean before(Object proxy, Object target, Method method, Object[] args) { System.err.println("反射方法前逻辑"); return false; } @Override public void around(Object proxy, Object target, Method method, Object[] args) { System.err.println("取代了被代理的方法"); } @Override public void after(Object proxy, Object target, Method method, Object[] args) { System.err.println("反射方法后逻辑"); } }
2. 在JDK动态代理中使用拦截器
定义一个动态代理类,组合进来拦截器,在invoke方法中实现拦截器逻辑
public class InterceptorJdkProxy implements InvocationHandler { private Object target; private String interceptorClass = null; //通过拦截器类名引入 public InterceptorJdkProxy(Object target, String interceptorClass) { this.interceptorClass = interceptorClass; this.target = target; } public static Object bind(Object target, String interceptorClass) { return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InterceptorJdkProxy(target, interceptorClass)); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 标识未设置拦截器,可以直接调用原方法返回 if(interceptorClass == null){ return method.invoke(target, args); } Object result = null; // 类名反射生成拦截器对象 Interceptor interceptor = (MyInterceptor)Class.forName(interceptorClass).newInstance(); if (interceptor.before(proxy, target, method, args)) { result = method.invoke(target, args); } else { interceptor.around(proxy, target, method, args); } interceptor.after(proxy, target, method, args); return result; } }
真正在invoke方法中实现拦截器的逻辑,内部都是调用了各种反射机制
测试:
public interface HelloWorld{ public void sayHelloWorld(); } class HelloWorldImp implements HelloWorld{ @Override public void sayHelloWorld(){ System.out.println("Hello World!"); } } // ------------------ public class InterceptorTest { public static void main(String[] args) { HelloWorld hwProxy = (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImp(), MyInterceptor.class.getName()); hwProxy.sayHelloWorld(); } }
输出:
反射方法前逻辑
取代了被代理的方法
反射方法后逻辑