Java動態代理Proxy&InvocationHandler 實例

代理類在程序運行時創建的代理方式被成爲 動態代理。 也就是說,這種情況下,代理類並不是在Java代碼中定義的,而是在運行時根據我們在Java代碼中的“指示”動態生成的。相比於靜態代理, 動態代理的優勢在於可以很方便的對代理類的函數進行統一的處理,而不用修改每個代理類的函數. 

話不多說, show you code . ...

 

1.定義代理的接口類.

public interface People {
    public String work();

}

2.定義接口的實現類.

import java.time.LocalDate;

public class Teacher implements People {
    @Override
    public String work() {
        System.out.println("上課=>"+ LocalDate.now() );
        return "上課";
    }
}

3.定義代理的實現類

這裏最重要的是構造函數和 invoke方法.

構造函數: 設置要被代理的對象.

invoke: 根據請求的方法&參數 . 構造代理實現

 


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

public class WorkHandler implements InvocationHandler {
    //代理類中的真實對象
    private Object obj;

    public WorkHandler() {
        // TODO Auto-generated constructor stub
    }
    //構造函數,給我們的真實對象賦值
    public WorkHandler(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("WorkHandler#invoke    "+proxy.getClass().getName());
        System.out.println("WorkHandler#invoke    "+this.obj.getClass().getName());

        //在真實的對象執行之前我們可以添加自己的操作
        System.out.println("before invoke。。。");
        Object invoke = method.invoke(obj, args);
        //在真實的對象執行之後我們可以添加自己的操作
        System.out.println("after invoke。。。");
        return invoke;
    }


}

 

4.定義運行方法


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

public class Client {

    public static void main(String[] args) {
        //要代理的真實對象
        People people = new Teacher();
        //代理對象的調用處理程序,我們將要代理的真實對象傳入代理對象的調用處理的構造函數中,最終代理對象的調用處理程序會調用真實對象的方法
        InvocationHandler handler = new WorkHandler(people);
        /**
         * 通過Proxy類的newProxyInstance方法創建代理對象,我們來看下方法中的參數
         * 第一個參數:people.getClass().getClassLoader(),使用handler對象的classloader對象來加載我們的代理對象
         * 第二個參數:people.getClass().getInterfaces(),這裏爲代理類提供的接口是真實對象實現的接口,這樣代理對象就能像真實對象一樣調用接口中的所有方法
         * 第三個參數:handler,我們將代理對象關聯到上面的InvocationHandler對象上
         */
        People proxy = (People) Proxy.newProxyInstance(handler.getClass().getClassLoader(), people.getClass().getInterfaces(), handler);

        System.out.println(proxy.work());

        System.out.println("Client#manin "+proxy.getClass());

    }

}

5. 輸出結果

WorkHandler#invoke    com.sun.proxy.$Proxy0
WorkHandler#invoke    org.apache.hadoop.reflect.Teacher
before invoke。。。
老師教書育人...
after invoke。。。
教書
Client#manin class com.sun.proxy.$Proxy0

 

 

 

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