動態代理一般比較難理解,程序設計者會設計一個攔截器接口供開發者使用。
開發者只需要攔截器接口的方法、含義和作用即可。
如下面的 Interceptor 接口類,開發者只需實現接口方法,自定義方法邏輯即可,如 MyInterceptor 類。
下面 MyInterceptor 攔截器實現的總體邏輯是:
設計者設置攔截器,開發者提供攔截器,調用方法前,執行攔截器的before()方法,如果爲true,則反射原來要執行的方法,如果false,則執行攔截器的around方法,最後不過true/false都會執行攔截器的after方法。
上面的調用方法後的邏輯操作,開發者可以再在代碼中自定義,這裏只是給個例子。。
定義接口:
public interface User {
void say(String str);
void haha();
}
定義接口實現類:
public class UserImp implements User {
@Override
public void say(String str) {
System.out.println("asd"+str);
}
@Override
public void haha() {
System.out.println("哈哈");
}
}
定義攔截器接口(給接口開發者用)
public interface Interceptor {
boolean before(Object proxy, Object target, Method method,Object[] args);
void around(Object proxy, Object target, Method method,Object[] args);
void after(Object proxy, Object target, Method method,Object[] args);
}
定義攔截器接口實現類(開發者自己實現)
/*
* 攔截器
* 三個方法的參數:
* 1.代理對象
* 2.需代理對象
* 3.方法
* 4.方法參數
* */
public class MyInterceptor implements Interceptor {
@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
System.out.println("反射方法前邏輯");
return true; // true則進行反射原方法,按需求自己改
}
@Override
public void around(Object proxy, Object target, Method method, Object[] args) {
System.out.println("取代了被代理對象的方法");
}
@Override
public void after(Object proxy, Object target, Method method, Object[] args) {
System.out.println("反射方法後邏輯");
}
}
定義使用攔截器的動態代理類(JDK)
/*
* JDK動態代理使用攔截器
* */
public class InterceptorJDKProxy implements InvocationHandler {
// 被代理對象
private Object target =null;
// 攔截器權限定類名,用於反射使用
private String interceptorClass= null;
public InterceptorJDKProxy(Object target, String interceptorClass) {
this.target = target;
this.interceptorClass = interceptorClass;
}
/*
* 獲取代理對象和設置攔截器
* 參數:
* obj:被代理對象
* interceptorClass:攔截器
* */
public static Object getProxy(Object obj,String interceptorClass){
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),new InterceptorJDKProxy(obj,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 = (Interceptor)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;
}
}
測試類:
/*
* 使用攔截器
* */
@Test
public void test2(){
User proxy = (User) InterceptorJDKProxy.getProxy(new UserImp(),"com.czk.base.reflect.Interceptor.MyInterceptor");
proxy.haha();
}
結果:
反射方法前邏輯
哈哈
反射方法後邏輯