代码之家  ›  专栏  ›  技术社区  ›  perp

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

  •  1
  • perp  · 技术社区  · 16 年前

    public class Foo {
        private int data;
    
        public int getData() {
            return data;
        }
    
        public void setData(int data) {
            this.data = data;
        }
    }
    

    我知道我可以用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());
        }
    }
    

    完全

    (我已经知道如何使用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 回复  |  直到 16 年前
        1
  •  3
  •   Péter Török    16 年前

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

        2
  •  1
  •   cletus    16 年前

    我建议你看看 AspectJ before advice