Summarize Robot-Turning Belt Example with Multibinding

I have this use case, which is very similar to the example of a Guice foot robot, except that I don’t know how many legs I have. Therefore, I cannot use the annotations necessary for the example of leg robots.

I expect to collect all these “legs” in java.util.Set with the Guice Multibindings extension.

Technically, in PrivateModule, I would like to present the implementation directly as a collection element that will be provided by the Multibindings extension. I just don't know how to do this.

For reference and sample code, see the robot foot example here: http://code.google.com/p/google-guice/wiki/FrequentlyAskedQuestions#How_do_I_build_two_similar_but_slightly_different_trees_of_objec


Here is my use case:

I have the following:

// 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 service. public void configure () { // How to make this public IN a multibinder 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 service. public void configure () { // How to make this public IN a multibinder set? bind(MyInterface.class).to(CircleImplementation.class); // Implementation specific to the Circle implementation. bind(MyTree.class).to(CircleTree.class); } } 

Since I'm talking about expansion jars, at first I don’t know them, I don’t even know how many they are: I need to load MyModule using juServiceLoader , and each module must define the implementation of MyInterface (these two parts are in order).

The problem is to get all implementations of MyInterface in one set (in MyManager ). How can i do this?


A solution based entirely on Jesse's answer:

 // 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); } 

This allows me not to force the "client" to extend the PrivateModule, but to use any implementation of the module, if MyModule is an interface that extends the module.

+6
source share
1 answer

It looks like you will need to jump over a few hoops into a simple-binding from a private module so that they can be in the multi-line interface of the top-level injector.

This should work:

 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); } } 

This workaround is necessary because multi-linking is necessary for the top-level injector. But the bindings of individual modules are not displayed to this injector, so you need to set them.

+9
source

Source: https://habr.com/ru/post/892335/


All Articles