2011-06-06 86 views
3

我想在Java中创建这样一个对象,它将包含一些类似Object getAttr(String name)的“调度器”函数,它将接收所有属性访问尝试 - 因此,如果我将执行System.out.print(myObj.hello)实际代码会被翻译成类似System.out.print(myObj.getAttr('hello'))的东西,如果我会做myObj.hello = 123,它应该执行为myObj.setAttr('hello', 123)。请注意,我应该可以使用任何属性名称,我不知道可能的名称列表提前。拦截Java字段和方法访问,创建代理对象

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

UPD#1:我正在为JVM编写新的语言(某种程度上(J | P)类似于Ython,所以我们称之为Jython),并采用非常紧凑的Java集成。想要的设计特性之一就是只需输入jythonObject.some_attribute即可无缝访问Java代码中的Jython对象属性。所以这里是交易。

休息日:通过AspectJ的使用AOP似乎是这样做的唯一可能的解决方案,所以谢谢大家的帮助,特别是托马斯最为突出的答案:)

回答

3

它使用纯Java,除了通过是不可能的。

注解处理器

使用自定义注解处理器,它实际上是一种字节码操作的为好。 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; 
    } 
} 
+0

注解是细而有力,但不幸的是,他们是在我的情况不适用。然而,AspectJ可能会有所帮助,但我不确定它会如何影响其他代码(我有兴趣尽可能使事物“开箱即用”)。而且我没有真正使用Synthetic Accessor Method,请你解释一下吗?直接在允许范围内访问Java时,Java是否会自动生成setter? – toriningen 2011-06-07 00:16:31

+0

@modchan - yes javac为上述字段生成setter和getter,并在访问该字段时使用它们('t.hello = ...';也用于读取访问)。 Eclipse(如果配置正确)实际上会对此提出警告,因为它比直接字段访问慢了一点。这些方法只能在一小部分案例中生成和使用(如果该字段是私人的或我认为是受保护的),所以它可能不适用于您。 – 2011-06-07 10:49:15

1

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

字节码操作

例如使用AspectJ:

2

如果我们保持严格在面向对象的理由,你的领域不应该从外面访问。所有的字段访问应该通过get/set方法完成。

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

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

如果我们知道你需要做什么,这将有所帮助。

+0

我已经更新了问题,所以你可以看到预期的用法。 – toriningen 2011-06-07 00:09:23

+0

关于动态代理 - 据我所知,如果我不拥有对象的接口(例如,如果它是“外来的”并且是完全动态的),动态代理对我来说帮不了多少忙? – toriningen 2011-06-07 00:12:17

+0

@modchan你对动态代理的假设是正确的。看看更新后的问题,我会投票选择手动字节码操作作为解决方案。 – biziclop 2011-06-07 12:45:59