2010-03-06 38 views
1

比方說,我有一個普通簡單的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. 

有沒有辦法做到這一點?

回答

3

如果通過「實施」來表示「源代碼」,也許方面可以幫助你。通過AOP,您可以將類似這樣的內容添加到您的類方法中,並且一些AOP實現可以更改類的字節碼,從而確保檢測到您的類的所有用法。

如果字節碼本身不能被修改,你可能會運氣不好。

+0

是的,我的意思是源代碼。我很欣賞AOP的建議,儘管感覺像用大象槍殺蚊子一樣。但也許沒有簡單的方法? – perp 2010-03-06 14:48:26

+3

@perp不是我所知道的。你想做魔術,而且這很少是簡單的 - 即使它看起來像是;-) – 2010-03-06 15:12:29