代理類在程序運行時創建的代理方式被成爲 動態代理。 也就是說,這種情況下,代理類並不是在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