我正在使用javassist ProxyFactory
创建代理。创建单个代理时,一切正常。
但是,当我将代理对象传递给代理机制时,它会以
失败javassist.bytecode.DuplicateMemberException:重复方法:com.mypackage.Bean中的setHandler _ $$ _ javassist_0 _ $$ _ javassist_1
我用这个创建代理:
public Object createProxiedInstance(Object originalInstance) throws Exception {
Class<?> originalClass = instance.getClass();
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(originalClass);
factory.setHandler(new MethodHandler() {..});
Class<T> proxyClass = factory.createClass();
return proxyClass.newInstance();
}
那么,我该如何创建代理的代理呢?
更新:实际问题是每个代理都实现了定义ProxyObject
方法的setHandler(..)
。所以第二个代理正在尝试重新定义该方法,而不是在子类中重写它。
答案 0 :(得分:4)
问题是(实际上,它与CGLIB相同 - 我尝试使用commons-proxy)我不应该尝试创建代理类的代理类。第二个代理应该再次是原始类。因此,添加以下行可以解决问题:
if (instance instanceof ProxyObject) {
originalClass = originalClass.getSuperclass();
}
一个建议 - 如果你可以使用某种拦截器(比如commons-proxy中定义的拦截器),那就不要使用多个代理。
答案 1 :(得分:1)
这是一个相当晚的答案,但你可能仍然有兴趣了解这一点:
Javassist代理实现得相当天真。在上面的代码中,Javassist将始终使用以下方法创建代理类:
getHandler
)和(b)设置代理处理程序(setHandler
)后两种方法的名称由Javassist硬编码,由ProxyObject
接口表示。如果您现在创建代理类的代理类,Javassist将安排两次ProxyObject
方法的创建。一旦达到第一个条件,一次达到第二个条件。
您可以通过设置MethodFilter
来避免这种情况,该ProxyObject
指定不覆盖ProxyObject
的方法,以便javassist只能通过第二个条件创建方法。但是,这意味着您不能再为超类代理设置{{1}}而不通过反射直接访问相应的字段。因此,您的方法可能是最干净的。
cglib定义每个类的回调而不是每个实例的回调,这样cglib的这个问题稍有不同,但会导致另一个冲突。
但是,如果你想创建没有这些缺点的代理类,你可能会对我的库Byte Buddy感兴趣,这是我在使用cglib和javassist在遇到极端情况时感到沮丧时所写的。如果您正在使用运行时代码生成,我希望它可能有助于为您提供其他库所缺乏的灵活性。