使用Cglib進行動態代理的重點

示例:

public class InstanceProxyUtils {

    //被代理的對象
    public static class T {

        public void f() {
            System.out.println("測試");
        }

    }

    public static class TMethodInvokeInterceptor implements MethodInterceptor {


        /**
         * 1. 代理對象的類是被代理類的子類
         * <p>
         * 2. 代理對象重寫了父類的所有方法
         * 重寫的結果時:調用代理對象的任何方法都會觸發MethodInterceptor.intercept
         * <p>
         * 3. 當調用代理對象的方法時會將  代理對象自身/真實方法/調用參數/代理方法(調用時直接觸發的方法,代理對象對父類方法的重寫)  封裝起來作爲MethodInterceptor.intercept方法的入參
         * <p>
         * 4. method.invoke(真實對象,params) 等價於 methodProxy.invokeSuper(代理對象,params)
         * <p>
         * 5. 注意:第一個參數(代理對象)慎用
         * 5.1 切勿在MethodInterceptor.intercept方法中調用第一個參數proxy的任何方法,會引發無限遞歸最終OOM
         * proxy.toString->MethodInterceptor.intercept->proxy.toString->MethodInterceptor.intercept->......
         *
         * @param proxy       代理對象
         * @param method      被代理的類中的真實方法
         * @param objects     調用時傳入的參數
         * @param methodProxy 代理對象中的代理方法
         * @return 方法返回值
         */
        @Override
        public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

            //這樣也是允許的,等價於 method.invoke(new T(), objects);
            methodProxy.invoke(new T(), objects);

            //這樣調用是允許的
            methodProxy.invokeSuper(proxy, objects);

            //這樣調用是不允許的,將會報強轉異常,方法中會嘗試將第一個參數強轉爲代理對象
            //methodProxy.invokeSuper(new T(), objects);

            //這樣會導致無限遞歸 method.invoke(proxy, objects)->MethodInterceptor.intercept->method.invoke(proxy, objects)->MethodInterceptor.intercept->....
            //method.invoke(proxy, objects);

            //這樣將會導致無限遞歸,原因和method.invoke(proxy, objects);相同
            //methodProxy.invoke(proxy, objects);

            return null;
        }
    }

    public static void main(String[] args) {

        //代理對象的構建器
        Enhancer enhancer = new Enhancer();

        //設置代理對象的父類
        enhancer.setSuperclass(T.class);

        //設置代理對象方法回調
        enhancer.setCallback(new TMethodInvokeInterceptor());

        //構建代理對象
        T o = (T) enhancer.create();

        o.f();


    }


}

幾點疑問的解答:

        1. 代理對象是否必須指向一個被代理對象?

                否!根據實際需求,可以自定義攔截後的相關邏輯。

 

 

 

 

 

 

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