好的,所以这对你们来说是某种理论问题。
我正在试验 cglib 的 Enchancer - 为一个类创建一个代理。我的代码在 Felix OSGi 容器中运行。
层次结构看起来类似于:
// Bundle A;
// Imports-Package: javax.xml.datatype
// Exports-Package: a.foo
package a.foo;
public class Parent {
protected javax.xml.datatype.XMLGregorianCalendar foo;
... -> getter/setter;
}
// Bundle B
// Imports-Package: a.foo
// DOES NOT IMPORT PACKAGE javax.xml.datatype !!!
package b.bar;
import a.foo.Parent;
public class Child extends Parent {
protected String bar;
... -> getter/setter;
}
// Bundle B
// Code extracted from https://github.com/modelmapper/modelmapper/blob/master/core/src/main/java/org/modelmapper/internal/ProxyFactory.java#L59
public Child enchance() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Child.class);
enhancer.setUseFactory(true);
enhancer.setUseCache(true);
enhancer.setNamingPolicy(NAMING_POLICY);
enhancer.setCallbackFilter(METHOD_FILTER);
enhancer.setCallbackTypes(new Class[] { MethodInterceptor.class, NoOp.class });
try {
return enhancer.createClass();
} catch (Throwable t) {
t.printStackTrace();
}
}
从 OSGi 的角度来看 - 两个捆绑包 - 捆绑包 A 和捆绑包 B 功能齐全。包导入/导出是 bnd 生成的。尽管 BundleA 没有明确导入 javax.xml.datatype 包 - 我可以毫无问题地创建 Child 的实例。到现在为止还挺好。
但是当我尝试调用 enchance() 方法并创建子代理时 - cglib 抛出 NoClassDefFoundError: javax.xml.datatype.XMLGregorianCalendar
好的,我明白了——BundleB 的类加载器确实无法加载这个类,事实上——cglib 的 Enchancer 似乎正在使用 BundleB 的类加载器(Child 的类类型类加载器)来创建代理。
另一方面——为了处理模块化,OSGi 容器正在执行所谓的类加载委托——而不是 BundleB 的类加载器,OSGi 运行时将父类 Parent 的加载委托给 BundleA 的类加载器,后者知道如何加载其所有字段。这就是为什么 BundleB 不需要显式导入 javax.xml.datatype 包并且不需要知道如何加载 XMLGregorianCalendar 类并且仍然能够使用 Child 对象的原因。
我想知道 - 这种“委托”方法是否也适用于 cglib 的用例?请注意,我对字节码操作一无所知,这对某些人来说可能是一个非常愚蠢的问题。但我真的不明白 - 为什么 cglib 不能将 Parent 的加载委托给 Parent 自己的类加载器?cglib中真的没有这种机制吗?为什么?cglib 不与 OSGi 结合使用吗?如果是,那为什么?