JAVA中的JDK的動態代理
阿新 • • 發佈:2018-12-13
在java的動態代理機制中,有兩個重要的類或介面,一個是 InvocationHandler(Interface)、另一個則是 Proxy(Class)
當我們通過代理物件呼叫一個方法的時候,這個方法的呼叫就會被轉發為由InvocationHandler這個介面的 invoke 方法來進行呼叫。
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
proxy: 指代我們所代理的那個真實物件
method: 指代的是我們所要呼叫真實物件的某個方法的Method物件
args : 指代的是呼叫真實物件某個方法時接受的引數
接下來我們來看看Proxy這個類的newProxyInstance 這個方法::
public static Object newProxyInstance
(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
這個方法的作用就是得到一個動態的代理物件,其接收三個引數,我們來看看這三個引數所代表的含義:
loader: 一個ClassLoader物件,定義了由哪個ClassLoader物件來對生成的代理物件進行載入
interfaces: 一個Interface物件的陣列,表示的是我將要給我需要代理的物件提供一組什麼介面,如果我提供了一組介面給它,那麼這個代理物件就宣稱實現了該介面(多型),這樣我就能呼叫這組介面中的方法了
h: 一個InvocationHandler物件,表示的是當我這個動態代理物件在呼叫方法的時候,會關聯到哪一個InvocationHandler物件上
示例程式碼:
/** * @program: Maven * @description: 介面 * @author: hw * @create: 2018-12-07 17:00 **/ public interface Subject { public void rent(); public void hello(String str); } /** * @program: Maven * @description: 真實物件 * @author: hw * @create: 2018-12-07 17:00 **/ 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); } }
動態代理類
/**
* @program: Maven
* @description: 動態代理類
* @author: hw
* @create: 2018-12-07 17:01
**/
public class DynamicProxy 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("before rent house");
System.out.println("Method:" + method);
// 當代理物件呼叫真實物件的方法時,
// 其會自動的跳轉到代理物件關聯的handler物件的invoke方法來進行呼叫
method.invoke(subject, args);
// 在代理真實物件後我們也可以新增一些自己的操作
System.out.println("after rent house");
return null;
}
}
測試類
/**
* @program: Maven
* @description: 測試
* @author: hw
* @create: 2018-12-07 17:01
**/
public class Client {
public static void main(String[] args) {
// 我們要代理的真實物件
Subject realSubject = new RealSubject();
// 我們要代理哪個真實物件,就將該物件傳進去,最後是通過該真實物件來呼叫其方法的
InvocationHandler handler = new DynamicProxy(realSubject);
/*
* 通過Proxy的newProxyInstance方法來建立我們的代理物件,我們來看看其三個引數
* 第一個引數 handler.getClass().getClassLoader() ,
* 我們這裡使用handler這個類的ClassLoader物件來載入我們的代理物件
*
* 第二個引數realSubject.getClass().getInterfaces(),
* 我們這裡為代理物件提供的介面是真實物件所實行的介面,
* 表示我要代理的是該真實物件,這樣我就能呼叫這組介面中的方法了
*
* 第三個引數handler, 我們這裡將這個代理物件關聯到了上方的 InvocationHandler
* 這個物件上
*/
Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
.getClass().getInterfaces(), handler);
System.out.println(subject.getClass().getName());
//呼叫方法
subject.rent();
subject.hello("world");
}
}