[英]Generalize guice's robot-legs example with Multibinding
我有這個與 Guice 的機器人腿示例非常相似的用例,除了我不知道我有多少“腿”。 因此我不能使用機器人腿示例所需的注釋。
我希望將所有這些“腿”收集在帶有 Guice 的 Multibindings 擴展的 java.util.Set 中。
從技術上講,在 PrivateModule 中,我想將實現直接公開為將由 Multibindings 擴展提供的集合的元素。 我只是不知道該怎么做。
有關參考和代碼示例,請參見此處的機器人腿示例: http://code.google.com/p/google-guice/wiki/FrequentlyAskedQuestions#How_do_I_build_two_similar_but_slightly_different_trees_of_objec
這是我的精確用例:
我有以下內容:
// Main application
public interface MyTree {...}
public interface MyInterface {
public MyTree getMyTree() {}
}
public abstract class MyModule extends PrivateModule {}
public class MyManager {
@Inject MyManager (Set<MyInterface> interfaces){ this.interfaces = interfaces }
}
public class MainModule extends AbstractModule {
public void configure () {
// Install all MyModules using java.util.ServiceLoader.
}
}
// In expansion "square.jar"
public class SquareTree implements MyTree {...}
public class SquareImplementation implements MyInterface {
@Inject SquareImplementation (MyTree tree) { this.tree = tree; }
public MyTree getMyTree () { return this.tree; }
}
public class SquareModule extends MyModule { // correctly defined as a ServiceLoader's service.
public void configure () {
// How to make this public IN a multibinder's set?
bind(MyInterface.class).to(SquareImplementation.class);
// Implementation specific to the Squareimplementation.
bind(MyTree.class).to(SquareTree.class);
}
}
// In expansion "circle.jar"
public class CircleTree implements MyTree {...}
public class CircleImplementation implements MyInterface {
@Inject CircleImplementation (MyTree tree) { this.tree = tree; }
public MyTree getMyTree () { return this.tree; }
}
public class CircleModule extends MyModule { // correctly defined as a ServiceLoader's service.
public void configure () {
// How to make this public IN a multibinder's set?
bind(MyInterface.class).to(CircleImplementation.class);
// Implementation specific to the Circle implementation.
bind(MyTree.class).to(CircleTree.class);
}
}
由於我說的是擴展jars,所以一開始我並不認識它們,我什至不知道它們有多少個:我需要用juServiceLoader
加載MyModule
並且每個模塊都應該定義一個MyInterface
實現(這些兩部分都可以)。
問題是將所有MyInterface
實現放在一組中(在MyManager
中)。 我怎樣才能做到這一點?
解決方案,完全基於傑西的回答:
// Create the set binder.
Multibinder<MyInterface> interfaceBinder = Multibinder.newSetBinder(binder(), MyInterface.class, MyBinding.class);
// Load each module that is defined as a service.
for (final MyModule module : ServiceLoader.load(MyModule.class)) {
// Generate a key with a unique random name, so it doesn't interfere with other bindings.
final Key<MyInterface> myKey = Key.get(MyInterface.class, Names.named(UUID.randomUUID().toString()));
install(new PrivateModule() {
@Override protected void configure() {
// Install the module as part of a PrivateModule so they have full hands on their own implementation.
install(module);
// Bind the unique named key to the binding of MyInterface.
bind(myKey).to(MyInterface.class);
// Expose the unique named binding
expose(myKey);
}
});
// bind the unique named binding to the set
interfaceBinder.addBinding().to(myKey);
}
這允許我不強制“客戶”擴展 PrivateModule,而是在 MyModule 是擴展 Module 的接口時使用任何模塊實現。
看起來您需要跳過一些環節來促進來自私有模塊的綁定,以便它們可以在頂級注入器的多重綁定中。
這應該有效:
public class SquareModule extends AbstractModule { // does not extend PrivateModule
@Overide public void configure() {
// this key is unique; each module needs its own!
final Key<MyInterface> keyToExpose
= Key.get(MyInterface.class, Names.named("square"));
install(new PrivateModule() {
@Override public void configure() {
// Your private bindings go here, including the binding for MyInterface.
// You can install other modules here as well!
...
// expose the MyInterface binding with the unique key
bind(keyToExpose).to(MyInterface.class);
expose(keyToExpose);
}
});
// add the exposed unique key to the multibinding
Multibinder.newSetBinder(binder(), MyInterface.class).addBinding().to(keyToExpose);
}
}
這種解決方法是必要的,因為多重綁定需要在頂級注入器中發生。 但是該注入器看不到私有模塊綁定,因此您需要公開它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.