我正在使用 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 将始终使用以下方法创建一个代理类:

  1. 基类的任何可重写方法的方法
  2. (a) 获取代理处理程序的两种方法(getHandler) 和 (b) 设置代理处理程序 (setHandler)

后两个方法的名称由 Javassist 硬编码并由 ProxyObject 界面。如果您现在创建代理类的代理类,Javassist 会安排创建 ProxyObject的方法两次。一次满足第一个条件,一次满足第二个条件。

您可以通过设置来避免这种情况 MethodFilter 它指定不覆盖 ProxyObject的方法,这样 javassist 只会根据第二个条件创建方法。但是,这意味着您无法再设置 ProxyObject 对于超类代理,无需通过反射直接访问相应的字段。因此,您的方法可能是最干净的。

cglib 为每个类而不是每个实例定义回调,因此 cglib 的这个问题略有不同,但会导致另一个冲突。

但是,如果您想创建不受这些缺点影响的代理类,您可能对我的库感兴趣 字节好友 这是我在处理极端情况时使用 cglib 和 javassist 感到沮丧后写的。如果您正在使用运行时代码生成,我希望它可以帮助您提供其他库所缺乏的一些灵活性。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top