【问题标题】:Javassist: how to create proxy of proxy?Javassist:如何创建代理的代理?
【发布时间】:2014-05-03 22:33:35
【问题描述】:

我正在使用 javassist ProxyFactory 创建代理。创建单个代理时一切正常。

但是,当我将代理对象传递给代理机制时,它会失败

javassist.bytecode.DuplicateMemberException:重复方法:com.mypackage.Bean_$$_javassist_0_$$_javassist_1 中的 setHandler

我正在用这个创建代理:

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(..) 方法。所以第二个代理正在尝试重新定义方法,而不是在子类中覆盖它。

【问题讨论】:

  • 顺便说一句,这似乎是关于 javassist 的第一个问题。我很惊讶。

标签: java javassist


【解决方案1】:

问题是(实际上,它与 CGLIB 相同 - 我使用 commons-proxy 尝试过)我不应该尝试创建代理类的代理类。第二个代理应该再次属于原始类。因此添加以下行可以解决问题:

if (instance instanceof ProxyObject) {
    originalClass = originalClass.getSuperclass();
}

还有一个建议 - 如果您可以使用某种拦截器(如 commons-proxy 中定义的拦截器),请不要使用多个代理。

【讨论】:

    【解决方案2】:

    这是一个相当晚的答案,但您可能仍然有兴趣知道这一点:

    Javassist 代理的实现相当幼稚。在您上面的代码中,Javassist 将始终使用以下方法创建一个代理类:

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

    后两种方法的名称由 Javassist 硬编码并由ProxyObject 接口表示。如果您现在创建代理类的代理类,Javassist 将安排两次创建ProxyObject 的方法。第一个条件一次,第二个条件一次。

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-11
      • 2017-08-27
      • 1970-01-01
      相关资源
      最近更新 更多