比方說,我有一個普通簡單的Java類,如:監視對對象字段的數據「從外面」
public class Foo {
private int data;
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
}
...我現在想,追溯(即不改變Foo的實現),做一些魔術,這樣我就可以監視「數據」字段的變化。如果我只能監視setData()調用,我會非常高興。
我知道我可以使用java.lang.reflect.Proxy實例和InvocationHandler來做一些與之相近的事情。但是,只有在數據屬性通過代理更改(自然)時纔會涉及處理程序。而且據我所知,代理需要實現一個可用的接口。所以下面的例子工作正常:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface IFoo {
public void setData(int data);
}
class Foo implements IFoo {
private int data;
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
}
class MyInvocationHandler implements InvocationHandler {
private final Object monitoredInstance;
public MyInvocationHandler(Object monitoredInstance) {
this.monitoredInstance = monitoredInstance;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Invoked!");
return method.invoke(monitoredInstance, args);
}
}
public class ProxyTest {
public static void main(String[] args) throws Exception {
Foo foo = new Foo();
IFoo fooProxy = (IFoo) Proxy.newProxyInstance(
Foo.class.getClassLoader(),
new Class[]{IFoo.class},
new MyInvocationHandler(foo));
fooProxy.setData(42);
System.out.println("foo data = " + foo.getData());
}
}
但我與上述問題是需要靜態定義的IFoo接口。如上所述,我正在尋找一種解決方案,我不需要修改Foo 的所有的實現。我已經想出瞭如何使用Java Compiler API動態創建,編譯和加載IFoo等接口,我可以遍歷Foo.class的方法名稱,找到所有「setter」,並創建一個接口但是,在確定了所有這些之後,我不確定它會對我有什麼幫助。:-))
我希望所有監控業務對Foo實例的用戶都是完全透明的。我的願望是,我可以結束了一些非常苗條的東西,如:
Foo foo = new Foo();
ObjectMonitor om = new ObjectMonitor();
om.monitor(foo);
foo.setData(42); // The ObjectMonitor should notice this.
有沒有辦法做到這一點?
是的,我的意思是源代碼。我很欣賞AOP的建議,儘管感覺像用大象槍殺蚊子一樣。但也許沒有簡單的方法? – perp 2010-03-06 14:48:26
@perp不是我所知道的。你想做魔術,而且這很少是簡單的 - 即使它看起來像是;-) – 2010-03-06 15:12:29