2016-05-27 3 views
0

Google Guiceで最近ハッキングしましたが、宣言されているクラスに従ってStringをコンストラクタに挿入するアイデアが出てきました。注釈に定義された他のいくつかのパラメータ。たとえば、次の 私は@NamedInjectableはGuiceのが使用する新しい修飾子アノテーションを定義する場合:Guiceを使用してインデックス付き(およびクラス固有の)文字列を挿入する方法

@Documented 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ ElementType.FIELD, ElementType.PARAMETER }) 
@Qualifier 
public @interface NamedInjectable 
{ 
    String name() default ""; 

    boolean indexed() default true; 
} 
名(デフォルトは唯一のクラスの名前です)は、文字列の新しい名前ベースのある

、およびindexed状態かどうか新しい文字列が挿入されるたびに名前をインクリメントする必要はありません。

public MyClass { 
    @Inject 
    public MyClass(@NamedInjectable(name = "foo", indexed = true) String name) { 
     // some code 
    } 
} 

そしてname paramが、そのような「 私はプロバイダーバインディングまたはAssistedInjectを使用して考えられますが、私はそれを成し遂げることができた。失敗する一つの主な理由、何とかの名前を取得しているように値を指定する必要がありますクラス。

あなたが他のアイデアを持っていますか?

答えて

3

名前に基づいて標準バインディングのGuiceをカスタマイズする組み込みの方法はありません。あなたは一人のGuiceに固執する場合、あなたはおそらくが必要になります。

標準のインジェクション駆動注射に加えて、Guiceにはカスタム注入用のフックが含まれています。これにより、Guiceは独自のインジェクションセマンティクスやアノテーションを持つ他のフレームワークをホストすることができます。ほとんどの開発者はカスタムインジェクションを直接使用しません。拡張機能やサードパーティのライブラリで使用されることがあります。各カスタムインジェクションには、タイプリスナー、インジェクションリスナー、およびそれぞれの登録が必要です。カスタム注射用のGuiceのドキュメントの例では、あなたが、それをしたい何かがあなたから作成したアノテーションのパラメータを読み取ることが何より難しいように非常に鳴らない注入クラスの型でカスタマイズロガーインスタンスを、実証

あなたのTypeListener内で。しかし、これは@Injectアノテーションやコンストラクタでは直接動作しないため、インジェクションを完全にバックグラウンドで実行しようとすると問題が発生する可能性があります。

もうひとつの選択肢がはるかに簡単です。ファクトリを使用し、新しく構築されたクラスを渡すだけです。

public MyClass { 
    private final String name; 

    @Inject 
    public MyClass(NameInjector nameInjector) { 
     this.name = nameInjector.get(this, "foo", true); 
    } 
} 
+0

私は、私の目的にはるかに適している工場の注射を見つける。それは過度の=のように思えるが) –

1

通常のGuice注射では、何かが注入されているクラスの名前にアクセスすることはできません。本当にそれが必要な場合は、カスタムインジェクションを使用する必要があります。

カスタムTypeListenerを使用すると、注入イベントをリッスンし、注入されているクラスを知ることができます。注射イベントを聞いて、Guiceがの後にを呼び出すカスタムMembersInjectorを登録することができます。このMembersInjectorは、完全に構築されたクラスのインスタンスにアクセスできるため、フィールドに反映して注釈を検査することができます。ただし、オブジェクトがすでに作成されているため、コンストラクタパラメータを挿入することはできません。

つまり、コンストラクタパラメータのカスタム注入を行う方法はありません。しかし、あなたが言うアイデアは、フィールドインジェクションのために非常に可能です!MyMembersInjector<T>内で、その後

public class NamedStringListener implements TypeListener { 
    public <T> void hear(TypeLiteral<T> typeLiteral, TypeEncounter<T> typeEncounter) { 
     Class<?> clazz = typeLiteral.getRawType(); 
     while (clazz != null) { 
      for (Field field : clazz.getDeclaredFields()) { 
      if (field.getType() == String.class && 
       field.isAnnotationPresent(NamedInjectable.class)) { 
        Annotation annotation = field.getAnnotation(NamedInjectable.class); 

        // How you create and configure this provider is up to you. 
        Provider<String> provider = new MyStringProvider(clazz, annotation); 
        typeEncounter.register(new MyMembersInjector<T>(field, provider)); 
       } 
      } 
     clazz = clazz.getSuperclass(); 
     } 
    } 
} 

は、それが

まず行うにはどのように、あなたはTypeListener(リンクGuiceのWikiページに基づいて、このコード)を登録する必要があり

public class MyMembersInjector<T> implements MembersInjector<T> { 
    final Field field; 
    final Provider<String> provider; 

    NamedMembersInjector(Provider<String> provider) { 
     this.field = field; 
     this.provider = provider; 
     this.field.setAccessible(true); 
    } 

    public void injectMembers(T t) { 
     field.set(t, provider.get()); 
    } 
} 

MyStringProviderの実装をお任せします。

詳細はGuice CustomInjectionsのwikiページをご覧ください。

+0

Thnx。私は既にCustomInjectionsを試しました。私が理解しているように、フィールド注入は異なる理由で推奨されていません。 –

関連する問題