2011-08-08 56 views
6

我在我的当前项目BeanBinding了很多工作,所以我有代码看起来像......在运行时将方法名称转换为bean名称?

TypeA objA; 
TypeB objB; 
Bindings.createAutoBinding(UpdateStrategy.READ, 
    objA, BeanProperty.create("X"), 
    objB, BeanProperty.create("X")) 
    .bind(); 

objAobjB是有一个setX()方法的类的实例。问题在于,如果我重构setXsetY那么我需要搜索这些字符串属性名称。我意识到我可以为属性名称创建静态最终字符串,但如果我可以让编译器为我完成这项工作,那就更好了。

理想情况下,我想什么,能够做的是...

TypeA obja; 
TypeB objB; 
Bindings.createAutoBinding(UpdateStrategy.READ, 
    objA, BeanProperty.create(Magic.returnBeanName(TypeA.class).getX()), 
    objB, BeanProperty.create(Magic.returnBeanName(TypeB.class).setX()) 
    .bind(); 

这似乎这可以通过一些代码的合成和/或方面是可行的。

+0

在黑暗中的完整镜头,但也许'returnBeanName'可以使用javassist来创建一个对象,它采用每个getter方法,修改它的返回类型为String并返回属性名称?看起来很疯狂,但写起来很有趣。 – Jeremy

+0

@Jeremy:我想过你的建议,但为了使Eclipse和其他重构工具正常工作,方法签名必须保持不变,这对于制定者来说是一个真正的问题,因为他们会产生空洞,并且也会因为它们是“特殊的“ –

+0

我并不是说你应该修改bean本身。我的意思是你可以创建一个bean类的副本,方法名与你的bean完全相同,但是这些方法会返回属性的名称。 – Jeremy

回答

1

在黑暗中的一个完整的镜头,但也许returnBeanName可以使用javassist创建一个类似于该bean的不同的类,除了它将getter的返回类型修改为String并返回属性名称?

例如,如果你的bean是这样的:

public class Foo{ 
    private int x; 

    public int getX(){ 
     return x; 
    } 

    public void setX(int x){ 
     this.x= x; 
    } 
} 

然后动态地创建不同类,看起来像这样:

public class FooMeta{ 
    public String getX(){ 
     return "x"; 
    } 
} 

似乎那种疯狂,但听起来很有趣写。

+0

Janino可能很适合这里 –

+0

Nvm,janino是运行时只有 –

0

您可以使用instrumentation:使用ASM创建一个java agent以在编译时访问您的类并生成所需的类/接口/方法。这并不容易,你应该花时间学习Java工具,JVM字节码和ASM库,但是你可以用它来创造奇迹。

+0

是的,我真的知道该怎么做,但他们的问题在于,我现在需要将生成的类注册回eclipse,以便它可以处理重构。我希望有人会说一些lib/plugin已经存在的原因之一。 –

0

我做了什么像什么杰里米Heiler在我的开源项目,Funcito,你可以browse the source code看到需要做使用字节码操作,即使用了Javassist或CGLIB什么为例建议。

总体思路是,您使用Javassist或CGLIB的代码增强器将感兴趣的类作为具有方法拦截器的子类进行代理。您拦截方法调用并记录所调用方法的名称,然后转向并提取所调用的方法名称并根据需要使用它。您使用的语义与Funcito使用语义非常相似,这与您作为理想发布的内容非常接近。