2015-10-01 14 views
8

@RequiredArgsConstructorsのクラスがたくさんある私のプロジェクトではlombokを使用しています。私はこれらのコンストラクタをguiceで自動的に使用したいと思います。カスタム@Injectアノテーションを作成する

このオプションは、@RequiredArgsConstructors([email protected]__(@Inject))を使用することをお勧めしますが、これは醜い実験的なものです(read:将来はロンボクから消える可能性があります)。

私が考えているのは、カスタム注入注釈を作成することです。たとえば、@InjectOnlyConstructorと言うと、クラス定義を入れてguice's SPIを使用してこれらの型をバインドします。しかし、私はSPIでこれらのタイプを発見する方法を理解できません。

Guiceの要素を見て、guiceがデフォルトで拒否するこれらのコンストラクタにバインドするにはどうすればよいですか?

私はクラスが見えるようにしたいものの例:バックアップ計画として

@Singleton 
@InjectOnlyConstructor 
@RequiredArgsConstructor 
public class CatPictureService { 
    private final WebServiceClient client; 

    // Cool stuff that would make facebook cry 
} 

が、私は私のプロジェクトのパッケージをスキャンし、自動的にそれらのタイプをバインドするモジュールを持つことができます。

+0

トリックは[toConstructor()](http://google.github.io/guice/api-docs/latest/javadoc/com/google/inject/binder/LinkedBindingBuilder.html#toConstructor-java)を使用することです。 .lang.reflect.Constructor-)バインディング。私は後でより完全な解決策を書くでしょう! –

+0

@TavianBarnesはい!私はそれがバックエンドを完成させる方法だと思っていましたが、SPIを使用してバインドする必要があるタイプを発見するフロントエンドを見つけました(つまり、クラスパスをスキャンするのに不十分です)。 –

+0

接線:コンストラクタ、依存性注入だけでなく、さまざまな他のユースケースに必要です。ロンボクのonX機能のステータスが「不確実」であることを考えると、私はGuiceだけでなく他の人たちにも役立つより包括的な例を探しています。何か解決策はありますか? –

答えて

2

私はGuiceにバインドされていないタイプを解決することは不可能だと思っています。

私は4つのソリューションを考え出しました。最初の私のお気に入りです、それは一見明確な配線パターン公式Guiceの拡張子を使用しています。次のようにそれを使用する:

public class Bar { 
    private Bar(XYZ xyz) { ... } 
} 

Injector inject = Guice.createInjector(new AbstractModule() { 
    protected void configure() { 
     install(new OnlyConstructorBuilder(Bar.class)); 
    } 
}); 

OnlyConstructorBuilderは、例えば次のように定義される。

@RequiredArgsConstructor 
private static class OnlyConstructorBuilder extends AbstractModule { 
    private final Class<?> type; 

    @Override 
    protected void configure() { 
     bindToOnlyConstructor(type); 
    } 

    @SuppressWarnings("unchecked") 
    private <T> void bindToOnlyConstructor(Class<T> type) { 
     Constructor<T>[] ctors = (Constructor<T>[])type.getDeclaredConstructors(); 

     if (ctors.length > 1) { 
      addError("%s has too many constructors %s", type.getName(), Arrays.toString(ctors)); 
      return; 
     } else if (ctors.length < 1) { 
      addError("%s needs at least one constructor", type.getName()); 
      return; 
     } else { 
      bind(type).toConstructor(ctors[0]); 
     } 
    } 
} 

第二のアプローチは、クラスパスまたはそれに見える特定の注釈のための部分をスキャンすることです。これは私の元々のアイデアでした。グアバのリフレクションヘルパーを使用しているのであれば、それほど難しいことではありません。前と同じようなことをやったことがありますが、人々はそれも魔法のように感じます。結合部分は上記と同様である。

第3のアプローチは、モジュール内でbind(Bar.class)であり、要素SPIを使用して特定の注釈を持つUntargetedBindingを探します。しかし、すでにクラスをバインドしているので、唯一のコンストラクタにバインドすることもできます。

第4のアプローチは、最悪です。これはElements APIを使用し、すべてのバインディングの依存関係を決定します。特定のアノテーションを持つバインドされていない依存関係を検索します。これは私が降りたくない道です。

+0

'Module'クラスの' configure'では、(Reflectionsライブラリを使って)クラスパスの部分をスキャンし、それらを 'bindToOnlyConstructor'のようにバインドするのが私にとって最もクリーンな解決策のようです。 –

関連する問題