私はGoogleGuice 2.0で物を注入しようとしていますが、次の構造になっています。
FooAction implements Action
BarAction implements Action
次に、次のコンストラクターを持つActionLibraryがあります。
ActionLibrary (List<Action> theActions)
GuiceにActionLibraryのインスタンスをリクエストするとき、Guiceに登録済みの両方のActionクラス(FooAction、BarAction)を識別させ、それらをコンストラクターに渡します。ここでの動機は、3番目のアクションBazActionを追加すると、それをモジュールに登録するのと同じくらい簡単で、コンストラクターのリストに自動的に追加されるということです。
これは可能ですか?
これに必要なのは Multibindings です。具体的には、次のようにSet<Action>
(List
ではありませんが、Set
はおそらく本当に必要なものです)をバインドする必要があります。
Multibinder<Action> actionBinder = Multibinder.newSetBinder(binder(), Action.class);
actionBinder.addBinding().to(FooAction.class);
actionBinder.addBinding().to(BarAction.class);
次に、どこでも@Inject
Set<Action>
できます。
マルチバインディングのさらに良い方法と私が考えるものをお見せしましょう。 Action
sをプラグイン可能にして、誰でも追加できるようにしたい場合は、Module
をインスタンス化する必要を隠すために誰かが使用できる単純なMultibinder
を提供すると便利なことがよくあります。次に例を示します。
public abstract class ActionModule extends AbstractModule {
private Multibinder<Action> actionBinder;
@Override protected void configure() {
actionBinder = Multibinder.newSetBinder(binder(), Action.class);
configureActions();
}
/**
* Override this method to call {@link #bindAction}.
*/
protected abstract void configureActions();
protected final LinkedBindingBuilder<Action> bindAction() {
return actionBinder.addBinding();
}
}
なぜこれが良いのですか?これにより、誰かがどこからでもActionModule
を使用して、標準のバインディングAPIを介してAction
sを追加できます。読みやすいと思います。使用例は次のとおりです。
public final class MyStandardActionModule extends ActionModule() {
@Override protected void configureActions() {
bindAction().to(FooAction.class);
bindAction().to(BarAction.class);
// If you need to instantiate an action through a Provider, do this.
bindAction().toProvider(BazActionProvider.class);
// You can also scope stuff:
bindAction().to(MySingletonAction.class).in(Singleton.class);
}
}
Module
を使用してマルチバインダーを非表示にするこのパターンは、Guiceコードで使用されます。少し前もって作業しますが、物事をきれいに保ちます。必要に応じて、MapBinder
に対して同様のことを行うこともできます。必要な数のActionModule
をインスタンス化できることに注意してください。