Javassist:如何创建代理代理?

时间:2010-04-11 20:03:47

标签: java javassist

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

2 个答案:

答案 0 :(得分:4)

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

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

一个建议 - 如果你可以使用某种拦截器(比如commons-proxy中定义的拦截器),那就不要使用多个代理。

答案 1 :(得分:1)

这是一个相当晚的答案,但你可能仍然有兴趣了解这一点:

Javassist代理实现得相当天真。在上面的代码中,Javassist将始终使用以下方法创建代理类:

  1. 基类的任何可覆盖方法的方法
  2. 两种方法(a)获取代理处理程序(getHandler)和(b)设置代理处理程序(setHandler
  3. 后两种方法的名称由Javassist硬编码,由ProxyObject接口表示。如果您现在创建代理类的代理类,Javassist将安排两次ProxyObject方法的创建。一旦达到第一个条件,一次达到第二个条件。

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

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

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