我正在使用Javassist ProxyFactory创建一个Proxy类,其代码如下:
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(entity.getClass());
factory.setInterfaces(new Class[] { MyCustomInterface.class });
.....
Class clazz = factory.createClass();
Object result = clazz.newInstance();
问题是我还需要在课程中添加一个字段。但是,如果我CtClass proxy = ClassPool.getDefault().get(clazz.getName());
,则会发出NotFoundException
如何添加使用createClass创建的类的字段?有没有更好的方法来做我想做的事情?
答案 0 :(得分:6)
这取决于您对我的评论的回复。
您确实可以使用MyCustomInterface
和您的proxyClass在Java中创建mixin的排序。但是你仍然必须从代理类转换为MyCustomInterface
以便能够调用方法。
让我们开始吧。
首先,您已经在创建代理:
// this is the code you've already posted
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(entity.getClass());
factory.setInterfaces(new Class[] { MyCustomInterface.class });
Javassist代理允许您添加MethodHandler。它基本上是一个常规Java代理中的InvocationHandler,这意味着它可以作为一个方法拦截器。
方法处理程序将是你的mixin!首先,使用您实际要添加到类中的自定义字段以及您已开始代理的实体对象创建一个新的MethodHandler:
public class CustomMethodHandler implements MethodHandler {
private MyEntity objectBeingProxied;
private MyFieldType myCustomField;
public CustomMethodHandler(MyEntity entity) {
this.objectBeingProxied = entity;
}
// code here with the implementation of MyCustomInterface
// handling the entity and your customField
public Object invoke(Object self, Method method, Method proceed, Object[] args) throws Throwable {
String methodName = method.getName();
if(methodNameFromMyCustomInterface(methodName)) {
// handle methodCall internally:
// you can either do it by reflection
// or if needed if/then/else to dispatch
// to the correct method (*)
}else {
// it's just a method from entity let them
// go. Notice we're using proceed not method!
proceed.invoke(objectBeingProxied,args);
}
}
}
(*)请注意,即使我在评论中说要在内部处理调用,你也可以将接口实现放在另一个不是方法处理程序的地方,只需从这里调用它。
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(entity.getClass());
factory.setInterfaces(new Class[] { MyCustomInterface.class });
Class cls = factory.createClass();
// bind your newly methodHandler to your proxy
((javassist.util.proxy.Proxy) cls).setHandler(new CustomMethodHandler(entity));
EntityClass proxyEntity = cls.newInstance();
您现在应该可以执行((MyCustomInterface)proxyEntity).someMethodFromTheInterface()
并由CustomMethodHandler
请记住,这些方法并不完美,除非您首先创建代理,否则Entity类中的代码无法引用接口,这是其中一个缺点。
如果您不清楚任何事情,请发表评论,我会尽力澄清您。