简体   繁体   English

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

[英]Monitoring changes to object field data “from the outside”

Let's say I have a regular simple Java class, such as: 假设我有一个常规的简单Java类,例如:

public class Foo {
    private int data;

    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }
}

...and I now wish to, retroactively (ie without changing Foo's implementation), do some magic so that I can monitor the "data" field for changes. ......我现在希望追溯(即不改变Foo的实现),做一些魔术,以便我可以监视“数据”字段的变化。 I'd be perfectly happy if I could just monitor setData() invocations. 如果我能监视setData()调用,我会非常高兴。

I know I could do something close to this, using a java.lang.reflect.Proxy instance and an InvocationHandler. 我知道我可以使用java.lang.reflect.Proxy实例和InvocationHandler来做一些接近这个的事情。 However, the handler is only involved if the data property is changed through the proxy (naturally). 但是,只有在通过代理更改数据属性时(自然)才会涉及处理程序。 And also from what I understand, the proxy needs to implement an interface to become usable. 而且根据我的理解,代理需要实现一个可用的接口。 So the following example works fine: 所以下面的例子工作正常:

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());
    }
}

But my problem with the above is the need for the statically defined IFoo interface. 但我上面的问题是需要静态定义的IFoo接口。 As mentioned above, I'm looking for a solution where I don't have to modify the implementation of Foo at all . 正如上面提到的,我正在寻找一个解决方案,我没有在所有修改美孚的执行。

(I have figured out how to dynamically create, compile, and load interfaces like IFoo using the Java Compiler API. I could walk through the method names of Foo.class, find all "setters", and create an interface having those. Still, after figuring all that out, I'm not really sure it would help me at all. :-)) (我已经想出了如何使用Java编译器API动态创建,编译和加载像IFoo这样的接口。我可以浏览Foo.class的方法名称,查找所有“setter”,并创建一个具有这些的接口。在搞清楚这一切之后,我真的不确定它会对我有什么帮助。:-))

I would like all this monitoring business to be completely transparent to the user of Foo instances. 我希望所有这些监控业务对Foo实例的用户完全透明。 My wish is that I could end up with something really slim, like: 我的愿望是,我最终会得到一些非常苗条的东西,比如:

Foo foo = new Foo();
ObjectMonitor om = new ObjectMonitor();
om.monitor(foo);
foo.setData(42); // The ObjectMonitor should notice this.

Is there a way to do this? 有没有办法做到这一点?

If by "implementation" you mean "source code", maybe aspects can help you. 如果通过“实现”表示“源代码”,也许方面可以帮助您。 With AOP you can add things like this to your class methods, and some AOP implementations can alter the bytecode of your class, thus ensuring that all usage of your class is detected. 使用AOP,您可以将类似的内容添加到类方法中,并且一些AOP实现可以更改类的字节码,从而确保检测到类的所有用法。

If the bytecode itself can not be modified, you may be out of luck. 如果字节码本身无法修改,您可能会失败。

我建议你看看AspectJ,因为它可以像以前的建议那样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM