题
我正在使用 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(..)
方法。因此,第二个代理尝试重新定义该方法,而不是在子类中覆盖它。
解决方案
但问题是(实际上,它与CGLIB一样 - 我想它使用公共代理),我不应该尝试创建一个代理类代理类的。第二个代理应该再次成为原始类的。所以加入以下行解决问题:
if (instance instanceof ProxyObject) {
originalClass = originalClass.getSuperclass();
}
和一个建议 - 如果你可以使用某种类型的拦截器(如在公共代理中定义的),这样做的,而不是使用多个代理服务器
。其他提示
这是一个相当晚的答案,但您可能仍然有兴趣了解这一点:
Javassist 代理的实现相当简单。在上面的代码中,Javassist 将始终使用以下方法创建一个代理类:
- 基类的任何可重写方法的方法
- (a) 获取代理处理程序的两种方法(
getHandler
) 和 (b) 设置代理处理程序 (setHandler
)
后两个方法的名称由 Javassist 硬编码并由 ProxyObject
界面。如果您现在创建代理类的代理类,Javassist 会安排创建 ProxyObject
的方法两次。一次满足第一个条件,一次满足第二个条件。
您可以通过设置来避免这种情况 MethodFilter
它指定不覆盖 ProxyObject
的方法,这样 javassist 只会根据第二个条件创建方法。但是,这意味着您无法再设置 ProxyObject
对于超类代理,无需通过反射直接访问相应的字段。因此,您的方法可能是最干净的。
cglib 为每个类而不是每个实例定义回调,因此 cglib 的这个问题略有不同,但会导致另一个冲突。
但是,如果您想创建不受这些缺点影响的代理类,您可能对我的库感兴趣 字节好友 这是我在处理极端情况时使用 cglib 和 javassist 感到沮丧后写的。如果您正在使用运行时代码生成,我希望它可以帮助您提供其他库所缺乏的一些灵活性。