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(); } }
輸出:
反射方法前邏輯
取代了被代理的方法
反射方法后邏輯