わかりました、これは皆さんにとってある種の理論的な質問です。
クラスのプロキシを作成して、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 の観点から見ると、2 つのバンドル (バンドル A とバンドル B) は完全に機能します。パッケージのインポート/エクスポートは bnd によって生成されます。BundleA は javax.xml.datatype パッケージを明示的にインポートしませんが、問題なく Child のインスタンスを作成できます。ここまでは順調ですね。
しかし、enchance() メソッドを呼び出して子プロキシを作成しようとすると、cglib は NoClassDefFoundError: javax.xml.datatype.XMLGregorianCalendar をスローします。
OK、わかりました - BundleB のクラスローダは確かにこのクラスをロードできません。実際 - cglib のエンチャンサは、プロキシを作成するために BundleB のクラスローダ (子のクラス タイプ クラスローダ) を使用しているようです。
一方、モジュール性を処理するために、OSGi コンテナーは、いわゆるクラスローディング委任を行っています。BundleB のクラスローダーの代わりに、OSGi ランタイムは、親クラス Parent のロードを、すべてのフィールドをロードする方法を知っている BundleA のクラスローダーに委任します。これが、BundleB が明示的に javax.xml.datatype パッケージをインポートする必要がなく、XMLGregorianCalendar クラスをロードする方法を知る必要がなく、引き続き Child オブジェクトを操作できる理由です。
私は疑問に思っていました-そのような「委任」アプローチはcglibのユースケースにも適していませんか? 私はバイトコード操作について何も知らないので、非常にばかげた質問のように聞こえるかもしれません。しかし、私は本当に理解していません - cglib が親のロードを親自身のクラスローダーに委譲できないのはなぜですか? そのようなメカニズムは cglib では本当に利用できないのでしょうか? なんで?cglib は OSGi と組み合わせて使用されていませんか? もしそうなら、なぜですか?