6

Javaリフレクションを使用して(何らかの理由で)構築された多くのクラスがあるとします。ここで、 で注釈が付けられたフィールドに値をポストインジェクトする必要があります@PostInject

public class SomeClass {
  @PostInject
  private final String someString = null;

  public void someMethod() {
    // here, someString has a value.
  }
}

私の質問は:リフレクションを使用してフィールドを設定する高速な方法は何ですか?
多くのクラスでこれを非常に頻繁に行う必要があることを忘れないでください。そのため、パフォーマンスが重要です。

私が直感で行うことは、次の疑似コードで示されています。

  • クラスのすべてのフィールドを取得する
    clazz.getFields();
  • @PostInject で注釈が付けられているチェック
    eachField.getAnnotation(PostInject.class);
  • これらのフィールドにアクセスできるようにする
    eachAnnotatedField.setAccessible(true);
  • それらを特定の値に設定します
    eachAnnotatedField.set(clazz, someValue);

残念ながら、すべてのフィールドを取得するのは最も時間がかかります。
最初からフィールドを知っている場合、誰かがフィールドを取得できますか?

注: メソッドを使用してフィールドを設定できるようなインターフェイスをクラスに実装させることはできません。POJOが必要です。

注 2: ポスト フィールド インジェクションが必要な理由: API ユーザーの観点からは、final フィールドを使用できる必要があります。さらに、フィールドのタイプと数が事前に API によって認識されていない場合、インターフェイスを使用してフィールドの初期化を実現することは不可能です。

注 2b: ユーザーの観点からは、最終的な契約は破棄されません。最終的なままです。まず、フィールドが初期化され、その後変更できなくなります。ところで、この概念を使用する API はたくさんありますが、そのうちの 1 つが JAXB (JDK の一部) です。

4

5 に答える 5

7

オブジェクトを構築した直後にステップ 1 から 3 を実行し、取得したアノテーション付きフィールドのセットをオブジェクト自体に保存するか、クラスから set-of-annotated-fields への別のマップを保持することによって保存しますか?

次に、オブジェクトに挿入されたフィールドを更新する必要がある場合は、オブジェクトまたは別のマップからセットを取得し、手順 4 を実行します。

于 2009-10-28T12:16:20.013 に答える
1

それが良いかどうかはわかりませんが、このプロジェクトはあなたが望むことをするようです. 見積もり:

Java 1.5 およびジェネリックと互換性のある、依存関係のないクラスとそのフィールドの操作に関連するリフレクション ユーティリティとその他のユーティリティのセット。

ユーティリティは、高パフォーマンスの操作のためにリフレクション データをキャッシュしますが、弱い/ソフト キャッシュを使用して、開かれた ClassLoader を保持し、キャッシュがメモリに永続的に存在することを回避します。キャッシング メカニズムを独自のものでオーバーライドする機能がサポートされています。

于 2009-10-28T12:40:04.063 に答える
1

別のオプションは、最初から関連するいくつかのフィールドを知っていると言うように、それらのフィールドまたはメソッドのみを要求することです。

例 : java/lang/Class.htmlgetDeclaredMethodのまたはgetDeclaredFieldを参照してください。

于 2009-10-28T12:31:01.113 に答える
0

オブジェクトの構築に依存関係を注入できる既存のフレームワークを活用できます。たとえば、Spring では、aspectj 織りでそれを行うことができます。一般的な考え方は、Spring レベルで Bean の依存関係を定義し、オブジェクトの作成をアドバイスするためにターゲット クラスをマークするだけです。実際の依存関係解決ロジックは、クラスのバイトコードに直接注入されます (コンパイル時またはロード時のウィービングを使用できます)。

于 2009-10-28T13:00:41.393 に答える
0

リフレクションで何かを行う最も速い方法は、可能な限り実際のリフレクション API クラスをキャッシュすることです。たとえば、私はごく最近、別の動的 POJO マニピュレーターを作成しました。これは、私がこれを可能にするある時点で誰もが最終的に行うことの 1 つであると私は信じています。

Object o = ...
BeanPropertyController c = BeanPropertyController.of(o);

for (String propertyName : c.getPropertyNames()) {
        if (c.access(propertyName) == null && 
            c.typeOf(propertyName).equals(String.class)) {
                c.mutate(propertyName, "");
        }
}

それが機能する方法は、基本的に、Bean のすべてのプロパティを遅延ロードする 1 つのコントローラー オブジェクト (注: いくつかの魔法が関係しています) を持ち、実際のコントローラー オブジェクトが生きている限りそれらを再利用するというものです。私が言えることは、メソッドオブジェクト自体を保存するだけで、それを非常に高速なものに変えることができたということです。私はそれを非常に誇りに思っており、著作権などを整理できると仮定してリリースすることさえ考えています.

于 2009-10-28T19:55:10.853 に答える