Java代理(三) JDK動態代理

定義

動態代理類的源碼是在程序運行期間由JVM根據反射等機制動態的生成,所以不存在代理類的字節碼文件。代理類和委託類的關係是在程序運行時確定。

實現方式


在java的動態代理機制中,有兩個重要的類或接口,一個是 InvocationHandler(Interface)、另一個則是 Proxy(Class),這一個類和接口是實現我們動態代理所必須用到的。

每一個動態代理類都必須要實現InvocationHandler這個接口,並且每個代理類的實例都關聯到了一個handler,當我們通過代理對象調用一個方法的時候,這個方法的調用就會被轉發爲由InvocationHandler這個接口的 invoke 方法來進行調用。

java.lang.reflect.InvocationHandler#invoke
//proxy:指我們所代理的那個真實對象//method:真實對象調用的方法//args:傳入方法的參數
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
可以看出,現在還不知道代理類對象是什麼,這用到了另一個類:java.lang.reflect.Proxy
Proxy類的作用就是用來動態創建一個代理對象的類,它提供了許多的方法,但是我們用的最多的就是 newProxyInstance 這個方法

//返回 動態的代理對象
//loader: 加載代理對象的ClassLoader//interfaces:一個Interface對象的數組,代理類實現的這些接口列表//h:關聯到的InvocationHandler對象
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException

Java代碼案例:
package com.tlk.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created by tanlk on 2017/8/16 17:32.
 */
public class JDKDynamicProxyTest {

    interface Subject {
        public void test1();

        public void test2();
    }

    /**
     * 實現類1
     */
    static class MySubject1 implements Subject {
        public void test1() {
            System.out.println("MySubject1 test1 方法開始執行");
        }

        public void test2() {
            System.out.println("MySubject1 test2 方法開始執行");
        }
    }

    /**
     * 實現類2
     */
    static class MySubject2 implements Subject {
        public void test1() {
            System.out.println("MySubject2 test1 方法開始執行");
        }

        public void test2() {
            System.out.println("MySubject2 test2 方法開始執行");
        }
    }

    /**
     * 定義一個動態代理類,動態代理類必須要實現InvocationHandler接口
     */
    static class DynamicProxy implements InvocationHandler {

        private Subject target;

        //當代理對象調用真實對象的方法時,其會自動的跳轉到代理對象關聯的handler對象的invoke方法來進行調用
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("before ");
            method.invoke(target, args);
            System.out.println("end");
            return null;
        }

        //通過Proxy的newProxyInstance方法來創建我們的代理對象
        public Object getProxy(Subject target) {
            this.target = target;
            //動態生成代理類
            return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        }
    }

    public static void main(String[] args) {
        DynamicProxy dynamicProxy = new DynamicProxy();
        Subject subject = (Subject) dynamicProxy.getProxy(new MySubject1());
        System.out.println("生成的代理類:" + subject.getClass());
        subject.test1();

        subject = (Subject) dynamicProxy.getProxy(new MySubject2());
        System.out.println("生成的代理類:" + subject.getClass());
        subject.test2();
    }

}



動態代理優點:
1.上面只有一個proxy類,但可以代理多個實現,而靜態代理需要n個proxy類
2.通過invoke方法,在所有被代理的類的某些函數調用時觸發,一口氣完成所有對應代理的AOP(靜態代理需要在每個代理上進行AOP)

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