詳解java動態(tài)代理的2種實現(xiàn)方式
java的動態(tài)代理在接java的api上有說明,這里就不寫了。我理解的代理:
對特定接口中特定方法的功能進行擴展,這就是代理。代理是通過代理實例關聯(lián)的調(diào)用處理程序?qū)ο笳{(diào)用方法。
下面通過一個例子看一下:
接口:
public interface Num {
void show();
int getNum();
int getProduct(int x);
}
實現(xiàn)類:
public class MyNum implements Num {
@Override
public int getNum() {
return 3;
}
@Override
public int getProduct(int x) {
return x;
}
@Override
public void show() {
System.out.println("底層方法打印數(shù)字99");
}
}
先看一下Method中的invoke方法在api中是怎么描述的
就是說調(diào)用處理程序?qū)涌诘膶崿F(xiàn)類對象調(diào)用Method對象表示的底層方法。
第一種實現(xiàn)代理的方式:
public class NumProxy {
private Object num;
//通過構(gòu)造方法構(gòu)造接口的實現(xiàn)類對象
public NumProxy(Object num) {
this.num = num;
}
public Object getNumByProxy(){
Object numProxy = Proxy.newProxyInstance(num.getClass().getClassLoader(), new Class[]{Num.class}, new InvocationHandler() {
/**
* method: 對應于在代理實例上調(diào)用的接口方法的 Method 實例。我理解的就是被代理的真實方法實例
* args: 我理解的是真實方法的參數(shù)數(shù)組
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object obj = null;
System.out.println("在方法之前開始記錄");
String methodName = method.getName();
if("getProduct".equals(methodName)){
obj = method.invoke(num, args);
obj = (Integer) obj * 2;
System.out.println("proxy: getProduct()結(jié)束");
}
else if("show".equals(methodName)){
obj = method.invoke(num, args);
System.out.println("proxy: show()結(jié)束");
}
return obj;
}
});
return numProxy;
}
}
第二種實現(xiàn)代理的方式:通過實現(xiàn)InvocationHandler接口
public class NumProxyImpl implements InvocationHandler {
//這里我把接口類型具體化了, 沒有寫成Object
private Num num;
public NumProxyImpl(Num num){
this.num = num;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object obj = null;
String methodName = method.getName();
if("getProduct".equals(methodName)){
System.out.println("proxy: getProduct()開始");
obj = method.invoke(num, args);
obj = (Integer) obj * 2;
System.out.println("proxy: getProduct()結(jié)束");
}else if("show".equals(methodName)){
System.out.println("proxy: show()開始");
obj = method.invoke(num, args);
System.out.println("proxy: show()結(jié)束");
}
return obj;
}
}
測試代碼:
public class TestNum {
public static void main(String[] args) {
//兩種方式一起測試
NumProxy np = new NumProxy(new MyNum());
Num numProxy = (Num) np.getNumByProxy();
int x = numProxy.getProduct(2);
System.out.println(x);
numProxy.show();
System.out.println("----------------");
NumProxyImpl npi = new NumProxyImpl(new MyNum());
Num numPro = (Num) Proxy.newProxyInstance(Num.class.getClassLoader(), new Class[]{Num.class}, npi);
int n = numPro.getProduct(3);
System.out.println(n);
numPro.show();
}
}
控制臺結(jié)果:

第二種方式有點小疑惑,不知道大家有沒有,那就是并沒有顯示的調(diào)用NumProxyImpl中的invoke方法,可是卻執(zhí)行了,嗯嗯,這個自己下去看一下啊
不想麻煩的只需要記住就行了。
比如編碼的處理就可以用到代理,下次寫個例子。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
在webservice里調(diào)用耗時方法出錯的解決方案
這篇文章主要介紹了在webservice里調(diào)用耗時方法出錯的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07
SpringBoot+React實現(xiàn)計算個人所得稅
本文將以個人所得稅的計算為例,使用React+SpringBoot+GcExcel來實現(xiàn)這一功能,文中的示例代碼講解詳細,具有一定的學習價值,感興趣的小伙伴可以了解下2023-09-09

