有時候我們需要將某個任務讓別人帶我們做,比如,買個東西,我們不必自己跑過去買,這時我們可以讓某個人幫我們帶一下。在代碼,經(jīng)常用到場景是某個rpc調用,我們把這個調用交給一個代理來調用,調用者使用代理來調用,就好像調用本地方法一樣,從而對調用者無感知。今天我們來著重看下java動態(tài)代理的實現(xiàn)。
IHelloworld.java
public interface IHelloworld {
public void hello();
}
HelloworldImp.java
public class HelloworldImp implements IHelloworld {
@Override
public void hello() {
System.out.println("hello world");
}
}
這里我們定義了一個接口IHelloworld,然后用一個類實現(xiàn)了這個接口,然后我們需要用到了java的動態(tài)代理類Proxy,它的作用是用來創(chuàng)建代理類,代理類的創(chuàng)建對使用者來說是無感知的,它是在程序運行時動態(tài)創(chuàng)建的,下面我們看下它創(chuàng)建代理類的函數(shù):
public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h);
這個就是用來創(chuàng)建代理類的函數(shù):
loader:用于動態(tài)生成的代理類的加載,動態(tài)代理是在newProxyInstance中代碼生成了class文件,然后需要用classLoader加載,這里的loader就是用來加載動態(tài)代理類文件
interfaces:接口(Proxy只支持接口,不支持類)數(shù)組,代理類就是根據(jù)接口數(shù)組來生成的,生成的代理類實現(xiàn)了interfaces的所有接口
h:代理類的成員變量,在創(chuàng)建代理對象的時候,需要傳遞h變量作為構造函數(shù)的參數(shù)
return:返回的是代理類的對象
然后用戶拿到這個代理類的對象時,就可以調用接口的函數(shù),代理類在實現(xiàn)接口函數(shù)的內部調用了h.invloken(proxy, method, args),這時調用到了InvocationHandler的實現(xiàn)類。
public class ProxyInvokeImp implements InvocationHandler {
// 這個就是我們要代理的真實對象
private Object object;
//? ? 構造方法,給我們要代理的真實對象賦初值
public ProxyInvokeImp(Object object) {
this.object = object;
}
public void setObject(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("proxy class: " + proxy.getClass());
System.out.println("method: " + method.getName());
Object obj = method.invoke(object, args);
return obj;
}
}
在invoke中,我們利用反射調用函數(shù),object為HelloworldImp的對象,所以最后調用了真正的服務。在調用服務的前后可以實現(xiàn)代理的自己的一些行為。