监控“从外部”对象字段数据的更改

时间:2010-03-06 14:33:15

标签: java reflection

假设我有一个常规的简单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编译器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.

有办法做到这一点吗?

2 个答案:

答案 0 :(得分:3)

如果“实施”是指“源代码”,也许方面可以帮助您。使用AOP,您可以将类似的内容添加到类方法中,并且一些AOP实现可以更改类的字节码,从而确保检测到类的所有用法。

如果字节码本身无法修改,那么你可能会失败。

答案 1 :(得分:1)

我建议您查看AspectJ因为before advice可以这样做。