我有一个实现接口'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"));
}
}
答案 0 :(得分:0)
我想你知道cglib不能在Java中发生多重继承。 cglib所做的就是创建一个代理类来实现所有方法,并在添加到Mixin
生成器的任何(超级)类中找到所有接口。请注意,代理的超类仍然是Object
。
由于您要添加两个类C
和B
,这两个类都继承自实现接口A
的类I
,因此该接口将被添加两次到实现代理。但是,Java中不允许这样做,并且验证程序会在加载类时抱怨它。 cglib的想法是:我创建一个实现n
接口的新类,并为我提供n
个反馈类,其中包含与这些调用相同的签名方法。您定义了一个等效于:
I
至B
I
至C
但是cglib怎么能解决这个问题呢?它只能实现一次接口I
。但是,由于Mixin
通过将任何接口方法调用委托给其注册的反馈对象来工作,因此thiis无济于事。此反馈对象应该是您提供的B
还是C
的实例? Cglib无法为您做出决定,即使它当然应该为您提供更好的错误消息,而不是明确遵循协议。
顺便说一句,您正在使用内部cglib Mixin.Generator
。您应该正式使用公共Mixin#create(Class<?>[], Object[])
方法。如果你有兴趣,我会在how to use cglib上写一点。此外,官方API允许您决定将哪个接口映射到哪个反馈对象。此外,它允许您添加其他未映射的接口来实现,以便您的代理可以转换为此类型。