5

リフレクションを使用して、JSR-330 アノテーション付きクラスの依存関係を判別するために何らかの処理を行う必要があります。

Spring、Guice、PicoContainer など、JSR-330 準拠のすべての IoC コンテナーを十分に認識しています。ただし、依存関係を解決して注入するのではなく、依存関係を特定する必要があります。

つまり、少なくともリフレクション クラスの「解析」に関しては、JSR-330 実装を実装する必要があるということです。

JSR-330 仕様には、実装するのが少し面倒だと思う部分が 1 つあります。

@Inject でアノテーションが付けられた別のメソッドをオーバーライドする @Inject でアノテーションが付けられたメソッドは、インスタンスごとに注入リクエストごとに 1 回だけ注入されます。@Inject でアノテーションが付けられたメソッドをオーバーライドする @Inject アノテーションのないメソッドは注入されません。

つまり、サブクラスは、基本クラスのオートワイヤリング コントラクトを再定義できるだけでなく、(ポリモーフィズムを通じて) インジェクション フローにフックすることもできます。

ここに私の質問があります:クラス階層が与えられた場合、階層のある部分のメソッドが階層のさらに下にオーバーライドされているかどうかを確認する簡単な方法はありますか?

私の場合、これを行う最も簡単な方法は、階層のリーフからの再帰を使用することです。

private List<Method> getInjectableMethods(final Class<?> clazz) {
    // recursive stop condition
    if(clazz == null) {
        return emptyList();
    }

    // recursively get injectable methods from superclass
    final List<Method> allInjectableMethods = newLinkedList(getInjectableMethods(clazz.getSuperclass()));
    final List<Method> injectableMethods = newArrayList();

    // any overridden method will be present in the final list only if it is injectable in clazz
    for (final Method method : clazz.getDeclaredMethods()) {
        removeIf(allInjectableMethods, Methods.Predicates.overriddenBy(method));
        if (isInjectable(method)) {
            injectableMethods.add(method);
        }
    }
    allInjectableMethods.addAll(injectableMethods);

    return allInjectableMethods;
}

overriddenBy グアバのような述語については、次のことを確認します。

  • クラスを定義するメソッドは isAssignableFrom 関係にあります
  • メソッド名が同じ
  • メソッドの仮パラメータは同じです

結果の複雑さは、階層内のメソッドの数に関して O(n^2) になります。

それを達成するためのより簡単で効率的な方法、またはそのような機能を備えたライブラリがあるかどうか疑問に思っていました。Guava と Apache Commons の両方で失敗しました...

4

1 に答える 1

0

残念ながら、クラス グラフはルート方向にしかナビゲートできません。そのため、特定のクラスローダーで利用可能なすべてのクラスをチェックする以外に、すべての派生クラスを見つける方法はありません。IoC コンテナーは、具体的な実装を常に認識しているため (構成の一部です)、この問題はありません。

継承ツリーは通常、IDE によって構築されますが、知る限り、利用可能なすべてのソース/クラスに対して強引なインデックス作成を使用しています (手がかりについては、InteliiJ IDEA のコミュニティ版のソースを調べることができます)。

于 2012-03-13T14:51:01.667 に答える