【问题标题】:Intercepting Java field and method access, creating proxy objects拦截Java字段和方法访问,创建代理对象
【发布时间】:2011-06-06 15:24:35
【问题描述】:

我想在 Java 中创建这样的对象,它将包含一些“调度程序”函数,如 Object getAttr(String name),它将接收所有属性访问尝试 - 所以,如果我会这样做 System.out.print(myObj.hello),实际代码将被转换为类似System.out.print(myObj.getAttr('hello')),如果我会做myObj.hello = 123,它应该执行为myObj.setAttr('hello', 123)。请注意,我应该可以使用任何属性名称,我事先不知道可能的名称列表。

那么,在这种情况下,有可能吗?

UPD#1:我正在为 JVM 编写新语言(不知何故,类似于 (J|P)ython,所以我们称之为 Jython),其意图是非常紧密的 Java 集成。想要的设计特性之一是能够从 Java 代码中无缝访问 Jython 对象属性,只需键入 jythonObject.some_attribute。所以这就是交易。

已关闭:通过 AspectJ 使用 AOP 似乎是解决此问题的唯一可能解决方案,因此感谢大家的帮助,尤其是 Thomas 提供了最广泛的答案:)

【问题讨论】:

    标签: java attributes proxy introspection intercept


    【解决方案1】:

    不可能使用纯Java,除了通过:

    字节码操作

    例如使用 AspectJ。

    注释处理器

    使用自定义注释处理器,这实际上也是一种字节码操作。 Projekt Lombok 正在做这样的事情。

    合成存取方法

    也就是说,如果代码无论如何都使用合成访问器方法(在这种情况下,您理论上可以创建代理):

    public class Test {
        public static void main(String... args) {
            TestClass t = new TestClass();
            // this is actually calling a synthetic accessor method
            t.hello = "x";
        }
        static class TestClass {
            private String hello;
        }
    }
    

    【讨论】:

    • 注解很好很强大,但不幸的是它们不适用于我的情况。然而,AspectJ 可能会有所帮助,但我不确定它会如何影响其他代码(我有兴趣使事情尽可能“开箱即用”)。而且我并没有真正得到合成访问器方法,你能解释一下吗?在允许的范围内直接访问字段时,Java 会自动生成 setter 吗?
    • @modchan - 是的 javac 为上述字段生成 setter 和 getter,并在访问字段时使用它们(t.hello = ...;也用于读取访问)。 Eclipse(如果配置正确)实际上会警告您,因为它比直接字段访问慢一点。这些方法仅在一小部分情况下生成和使用(如果我相信该字段是私有的或受保护的),因此它可能不适合您。
    【解决方案2】:

    如果我们严格遵守 OOP 原则,则您的字段根本不应该从外部访问。所有字段访问都应通过 get/set 方法完成。

    并且可以通过dynamic proxies 拦截接口的方法。 (重要提示:您不能使用类,只能使用接口。)

    如果这不符合您的需求(尽管除非您正在编写第三方工具,它可能应该)那么只有混乱的方式,面向方面的编程或直接的字节码黑客。

    如果我们知道您需要这样做,那将会有所帮助。

    【讨论】:

    • 关于动态代理 - 据我了解,如果我不拥有对象接口(例如,如果它是“外来的”并且是完全动态的),动态代理对我没有多大帮助?
    • @modchan 您对动态代理的假设是正确的。查看更新后的问题,我会投票支持手动字节码操作作为解决方案。
    【解决方案3】:

    您必须使用 AspectJ (http://www.eclipse.org/aspectj/) 或其他 AOP 库。

    【讨论】:

      【解决方案4】:

      【讨论】:

        【解决方案5】:

        Groovy 语言有用于 AOP 的工具, 并且已经存在用于处理您的案例的小型库:https://github.com/nanonull/bean-trace

        【讨论】:

          猜你喜欢
          • 2012-05-16
          • 1970-01-01
          • 1970-01-01
          • 2012-03-30
          • 2015-05-16
          • 1970-01-01
          • 1970-01-01
          • 2020-02-19
          • 2013-03-05
          相关资源
          最近更新 更多