java實現動態代理時遇到的問題
阿新 • • 發佈:2019-02-06
java中實現動態代理,用InvocationHandler
和Proxy
就可以了。
所謂的動態代理,就是真正執行操作的物件不是原始的物件,就像A拜託B買東西,然後B買好東西后包裝好給A。
例:
void iTest() throws Exception {
Foo foo = new Foo();
IFoo obj = (IFoo) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{IFoo.class}, new MIncocationHandler(foo));
obj.say("hello world" );
}
class MIncocationHandler implements InvocationHandler {
private Object realObj;
public MIncocationHandler(Object obj) {
this.realObj = obj;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("begin method invoke" );
method.invoke(realObj, args);
System.out.println("after method invoke");
return proxy;
}
}
interface IFoo {
public void say(String str);
}
class Foo implements IFoo{
public void say(String str) {
System.out.println(str );
}
}
這樣我們就能在不破壞原來的程式碼的情況下,在程式碼執行的前後插入日誌等操作,spring的事務就是利用該原理,但是用的cglib實現的動態代理類的生成,這樣就不用定義介面了,如果按照上面寫的程式碼去實現的話是需要首先定義介面的。
備註:
反射只能得到該類本身的資訊,不能得到父類或者實現的介面的資訊。
介面中的變數是public static final的,方法是public的。
生成的動態代理類實現了Proxy
初始化中傳入的所有介面。如果是多個介面的話,就要在handler中的invoke方法中自己判斷是呼叫了哪一個類的方法,不能直接傳遞一個指定的物件了。
如果是多個介面的話,各個介面中的方法不能衝突,例如方法名稱一樣但是返回型別不同,這樣的話實現類就不能確定該實現哪一個方法,因此會初始化代理類失敗