Home > Software engineering >  Provide multiple bindings using MapBinder in Java
Provide multiple bindings using MapBinder in Java

Time:10-27

I am using Google's MapBinders to map an Event Listener (my own Custom interface) to an EventType.

            MapBinder<EventType, EventListener> eventEventHandlerMapBinder =
                    MapBinder.newMapBinder(binder(), EventType.class, EventListener.class);
            eventEventHandlerMapBinder
                    .addBinding(EventType.DUMMY_EVENT)
                    .to(DummyListener.class);

This lets me inject Map<EventType, Provider<EventListener>> eventEventHandlerMapBinder into my EventRegistry or wherever. I now want to map multiple EventListeners to one Event Type, i.e. for DUMMY_EVENT, I want DummyListener.class and AnotherDummyListener.class to be bound. How do I do that? I cannot do this, because MapBinder creates a Provider for the V:

    MapBinder<EventType, List> eventEventHandlerMapBinder2 =
            MapBinder.newMapBinder(binder(), EventType.class, List.class);
    eventEventHandlerMapBinder2
            .addBinding(EventType.DUMMY_EVENT)
            .to((Key<? extends List>) Arrays.asList(DummyListener.class, AnotherDummyListener.class));

CodePudding user response:

You can use a combination of MapBinder and Multibinder (but you would need to switch from List to Set, but I guess it shouldn't be an issue). Here is a working simple example:

    interface Service {
    }
    static class Service1 implements Service {
    }
    static class Service2 implements Service {
    }
    public static void main(String[] args) {
        var injector = Guice.createInjector(new AbstractModule() {
            @Override
            protected void configure() {
                var multibinder = Multibinder.newSetBinder(binder(), Service.class);
                multibinder.addBinding().to(Service1.class);
                multibinder.addBinding().to(Service2.class);

                var mapBinder = MapBinder.newMapBinder(binder(), new TypeLiteral<String>() {}, new TypeLiteral<Set<Service>>() {});
                mapBinder.addBinding("foo").to(Key.get(new TypeLiteral<Set<Service>>(){}));
            }
        });
        var map = injector.getInstance(Key.get(new TypeLiteral<Map<String, Set<Service>>>() {
        }));
        assert map.get("foo") != null;
    }

To distinguish between different Sets, you can use annotations, such as @Named/Names or use custom ones.

  • Related