创建用于多重继承的Java代理时是否为ClassFormatError?

时间:2014-01-29 16:55:29

标签: java proxy composite cglib

我有一个实现接口'I'的类'A'。我有两个类'B'和'C',每个扩展A并添加一个新方法。 C和B不会覆盖A中的任何方法。“B”类中的新方法具有与“C”不同的签名,新方法是C和B之间的唯一区别。我需要创建一个代理(排序) “B”和“C”对象的复合,应该具有A的所有方法和“B”和“C”中的新方法。

我尝试在CGLIB中使用Mixin $ Generator来创建复合代理,但我得到错误“java.lang.ClassFormatError:类文件中的重复接口名称”。

有没有人遇到过类似的情况?有任何解决这个问题的建议吗?

感谢您的时间。

以下是使用界面和所有类更新的代码。

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Mixin;
import net.sf.cglib.proxy.Mixin.Generator;

interface I {
    public boolean testSomething();
}

class A implements I {

    @Override
    public boolean testSomething() {
        boolean isRoot = true;
        System.out.println("Returning '" + isRoot + "' from '" + this + "' ...");
        return isRoot;
    }
}

class B extends A {
    public boolean isB() {
        boolean isRoot1 = true;
        System.out.println("Returning " + isRoot1 + " from : " + this);
        return isRoot1;
    }
}

class C extends A {
    public int getInt() {
        int someInt = 2;
        System.out.println("Returning " + someInt + " from : " + this);
        return someInt;
    }
}
    public class TestMixin {

        public static Object invokeMethod(Object target, String methodName)
                throws Exception {
            Method method = target.getClass().getMethod(methodName);
            return method.invoke(target);
        }

        public static Mixin newInstance(Object[] delegates) {
            return newInstance(null, delegates);
        }

        public static Mixin newInstance(Class[] interfaces, Object[] delegates) {
            Generator gen = new Generator();
            gen.setStyle(Mixin.STYLE_EVERYTHING);
            if(interfaces != null) {
                gen.setClasses(interfaces);
            }
            gen.setDelegates(delegates);
            return gen.create();
        }

        public static void main(String[] args) throws Exception {
           // B and C extend Class 'A' which implements 'I' interface
            B root1 = new B();
            C root2 = new C();
            A[] roots = { root1, root2 };
            Class<?>[] interfaces = new Class[] { B.class, C.class };
            // newInstance causes java.lang.ClassFormatError: Duplicate interface
            // name in class file com/mycom/cglib/B$$MixinByCGLIB$$831a43ec
            Mixin mixin = TestMixin.newInstance(interfaces, roots);
            System.out.println("Mixin Object: " + mixin);
            System.out.println(invokeMethod(mixin, "testSomething"));
            System.out.println(invokeMethod(mixin, "isB"));
            System.out.println(invokeMethod(mixin, "getInt"));
        }
    }

1 个答案:

答案 0 :(得分:0)

我想你知道cglib不能在Java中发生多重继承。 cglib所做的就是创建一个代理类来实现所有方法,并在添加到Mixin生成器的任何(超级)类中找到所有接口。请注意,代理的超类仍然是Object

由于您要添加两个类CB,这两个类都继承自实现接口A的类I,因此该接口将被添加两次到实现代理。但是,Java中不允许这样做,并且验证程序会在加载类时抱怨它。 cglib的想法是:我创建一个实现n接口的新类,并为我提供n个反馈类,其中包含与这些调用相同的签名方法。您定义了一个等效于:

的映射
  1. IB
  2. IC
  3. 但是cglib怎么能解决这个问题呢?它只能实现一次接口I。但是,由于Mixin通过将任何接口方法调用委托给其注册的反馈对象来工作,因此thiis无济于事。此反馈对象应该是您提供的B还是C的实例? Cglib无法为您做出决定,即使它当然应该为您提供更好的错误消息,而不是明确遵循协议。

    顺便说一句,您正在使用内部cglib Mixin.Generator。您应该正式使用公共Mixin#create(Class<?>[], Object[])方法。如果你有兴趣,我会在how to use cglib上写一点。此外,官方API允许您决定将哪个接口映射到哪个反馈对象。此外,它允许您添加其他未映射的接口来实现,以便您的代理可以转换为此类型。

相关问题