Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/400.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 监控对象字段数据的更改”;“从外面”;_Java_Reflection - Fatal编程技术网

Java 监控对象字段数据的更改”;“从外面”;

Java 监控对象字段数据的更改”;“从外面”;,java,reflection,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类,例如:

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.

有什么方法可以做到这一点吗?

我建议你看看能做到这一点的东西。

我建议你看看能做到这一点的东西。

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

如果字节码本身无法修改,您可能会运气不佳。

如果“实现”指的是“源代码”,那么方面可能会对您有所帮助。使用AOP,您可以向类方法中添加类似的内容,一些AOP实现可以更改类的字节码,从而确保检测到类的所有使用情况


如果字节码本身无法修改,您可能会倒霉。

是的,我指的是源代码。我很欣赏AOP的建议,尽管这感觉就像用象枪杀死蚊子一样。但也许没有比这更简单的方法了?@据我所知,这可能不是。你想要变魔术,而这很少是简单的——即使看起来很简单;-)是的,我指的是源代码。我很欣赏AOP的建议,尽管这感觉就像用象枪杀死蚊子一样。但也许没有比这更简单的方法了?@据我所知,这可能不是。你想要变魔术,而这很少是简单的——即使看起来很简单;-)