I am working with BeanBinding a lot in my current project and so I have code that looks like...
TypeA objA;
TypeB objB;
Bindings.createAutoBinding(UpdateStrategy.READ,
objA, BeanProperty.create("X"),
objB, BeanProperty.create("X"))
.bind();
Where objA
开发者_JAVA百科 and objB
are instances of classes that have a setX()
method. The problem comes in that if I refactor setX
to setY
then I need to hunt down these string property names. I realize I can create static final strings for property name but if I can get the compiler to do the work for me, all the better.
Ideally, what I would like to be able to do is...
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();
It would seem this could be possible via some code synthesis and/or aspects.
A complete shot in the dark, but maybe returnBeanName
can use javassist to create a different class similar to the bean, except that it modifies the return types of the getters to String and returns the property name?
For example, if your bean looks like this:
public class Foo{
private int x;
public int getX(){
return x;
}
public void setX(int x){
this.x= x;
}
}
Then dynamically create a different class that looks like this:
public class FooMeta{
public String getX(){
return "x";
}
}
Seem kind of crazy, but sounds fun to write.
You can use instrumentation: create a java agent using ASM to access your classes at compile time and generate the needed classes/interfaces/methods. It's not easy and you should invest time to learn about java instrumentation, JVM bytecode and the ASM library but you can do wonders with it.
I have done something like what Jeremy Heiler suggested in my open source project, Funcito, which you could browse the source code to see an example of what needs to be done to use byte code manipulation, using either Javassist or CGLIB.
The general idea is that you use a code enhancer from Javassist or CGLIB to proxy the class of interest as a subclass which has a method interceptor. You intercept the method call and record the name of the method invoked, and then turn around and extract that invoked method name and use it as you like. The semantics for your use would be very similar to the Funcito usage semantics, which is close to what you posted as your ideal.
精彩评论