假设我有一个常规的简单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.
有办法做到这一点吗?
答案 0 :(得分:3)
如果“实施”是指“源代码”,也许方面可以帮助您。使用AOP,您可以将类似的内容添加到类方法中,并且一些AOP实现可以更改类的字节码,从而确保检测到类的所有用法。
如果字节码本身无法修改,那么你可能会失败。
答案 1 :(得分:1)
我建议您查看AspectJ因为before advice可以这样做。