定義
動態代理類的源碼是在程序運行期間由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)