使用攔截器的動態代理

動態代理一般比較難理解,程序設計者會設計一個攔截器接口供開發者使用。

開發者只需要攔截器接口的方法、含義和作用即可。
如下面的 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();
}

結果:
反射方法前邏輯
哈哈
反射方法後邏輯

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章