0

わかりました、これは皆さんにとってある種の理論的な質問です。

クラスのプロキシを作成して、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 と組み合わせて使用​​されていませんか? もしそうなら、なぜですか?

4

2 に答える 2

0

ここで説明されている OSGi Class Loader Bridge のアイデアを組み合わせてみまし 。最近思いついた別のアイデア。

アイデアは、ユーザーの型の親型階層にあるクラス型のクラス ローダーを追跡することです。これらのクラスローダーは、ユーザーのタイプのバンドルのクラスローダーに認識されないタイプをロードするためのフォールバックとして後で使用できます。

次に、解決のためにこの新しいクラス ローダーを使用するように CGLIB の Enhancer に指示できます。

アイデアはここに示されています: https://github.com/modelmapper/modelmapper/pull/294

ただし、これについて経験豊富な OSGi スペシャリストの意見を聞きたいです。しかし、これまでのところこれは機能しているようです。間違っていることが証明されるまで、私は自分の答えを受け入れます。

于 2017-12-19T13:14:48.847 に答える