動態代理使用不在累述。InvocationHandler.invoke的第一個參數proxy值是newProxyInstance返回的動態代理類的實例,不是被代理的實例。
動態代理類Proxy是結合java底層實現的,通過純粹的java代碼實現比較困難。
需要java動態生成類的支持。
要創建一個可以代理任何接口的類:
1.必須要知道要被代理的接口列表;
2.要有一個可以加載這個代理類的ClassLoader;
3.為了能夠在調用被代理實例接口時能夠動態的添加需要的處理,需要一個接口回調,并在回調中采用反射的形式調用實際的實例方法。
實現過程:以下Proxy是實現動態代理的過程
public interface Subject{
public void rent();
public void hello(String str);
}
public class RealSubject implements Subject{
@Override
public void rent() {
System.out.println("I want to rent my house");
}
@Override
public void hello(String str) {
System.out.println("hello: " + str);
}
}
public class DynamicProxyHandler implements InvocationHandler {
// 被代理對象
private Object subject;
public DynamicProxy(Object subject) {
this.subject = subject;
}
@Override
public Object invoke(Object object, Method method, Object[] args) throws Throwable {
// 在代理真實對象前我們可以添加一些自己的操作
System.out.println("Method:" + method);
// 當代理對象調用真實對象的方法時,其會自動的跳轉到代理對象關聯的handler對象的invoke方法來進行調用
method.invoke(subject, args);
// 在代理真實對象后我們也可以添加一些自己的操作
System.out.println("after rent house");
return null;
}
}
public static void main(String[] args) {
Subject realSubject = new RealSubject();
InvocationHandler handler = new DynamicProxyHandler(realSubject);
Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
.getClass().getInterfaces(), handler);
System.out.println(subject.getClass().getName());
subject.rent();
subject.hello("world");
}
subject.getClass().getName()打印的值是:$Proxy0
猜測大概的$Proxy0類如下(可以通過反射查看其中的一部分實際內容):
// 類的包名應該是和Proxy在同一個包下
public class Proxy0 implements Subject {
private InvocationHandler handler;
public Proxy0(InvocationHandler handler) {
this.handler = handler;
}
public void rent() {
Thread.currentThread().getStackTrace()[2].getMethodName();
// 通過反射獲取當前函數名稱和參數列表,傳給invoke
Proxy.invoke(this, method, args);
}
public void hello(String str) {
Proxy.invoke(this, method, args);
}
}
InvocationHandler的實現可以多種多樣,根據不同需求進行不同實現。