1

I am new to Guice DI. And I would like to get my scenario clarified.

To put it simple, Is there any replacement of MapBinder through Guice @annotations?

My Scenario:

Interface A{}
Class A1 implements A{}
Class A2 implements A{}

I would like to Inject the implementation class of A as follows,

if(param = One) then Inject A1 to A
if(param = Two) then Inject A2 to A

I understand that the above could be done with MapBinder, but I would like to do it through annotations as follows,

Class A1 implements A
{     
@Inject(param = One)     
A1(){}    
}

Class A2 implements A
{     
@Inject(param = Two)     
A2(){}    
}

So making the class annotated with params could automatically picks and inject the class based on the parameter (One or Two).

Since @Inject cannot accept params, overriding @Inject would help in this scenario? if so, how do we do so?

Or Is this scenario could only be achieved through binding using MapBinder (The reason why I wouldn't want to use binder is that we would want to define the binding map of key value pair explicitly, but using annotations just simply annotate the implementation class with params - easier maintenance).

Thanks in advance.

Viswa
  • 1,357
  • 3
  • 18
  • 30
  • Hi - I believe you would use named bindings for this. Having class a doing `@Inject@Named("one")` and then bind your injection classes named to "one" or "two" – pandaadb Mar 15 '17 at 14:52

2 Answers2

3

From the JLS, §9.6,

"By virtue of the AnnotationTypeDeclaration syntax, an annotation type declaration cannot be generic, and no extends clause is permitted.

"A consequence of the fact that an annotation type cannot explicitly declare a superclass or superinterface is that a subclass or subinterface of an annotation type is never itself an annotation type. Similarly, java.lang.annotation.Annotation is not itself an annotation type."

So, no, "overriding [sic]" will not help, because no extending type can be an annotation type.

Lew Bloch
  • 3,364
  • 1
  • 16
  • 10
  • Thanks much. This helps. So Is there any replacement of MapBinder through Guice @annotations? – Viswa Mar 13 '17 at 06:40
3

To answer your follow-up questino, I believe what you are looking for are named injects. See this example:

public class GuiceNamedTest extends AbstractModule {

    public static void main(String[] args) {
        Injector i = Guice.createInjector(new GuiceNamedTest());
        i.getInstance(InstaceOne.class);
        i.getInstance(InstaceTwo.class);
    }

    @Override
    protected void configure() {
        Bean beanOne = new Bean();
        beanOne.name = "beanOne";

        Bean beanTwo = new Bean();
        beanTwo.name = "beanTwo";

        bind(Bean.class).annotatedWith(Names.named("one")).toInstance(beanOne);
        bind(Bean.class).annotatedWith(Names.named("two")).toInstance(beanTwo);

        bind(InstaceOne.class);
        bind(InstaceTwo.class);
    }


    public static class Bean {
        String name;
    }

    public static interface A {}

    public static class InstaceOne implements A {

        @javax.inject.Inject
        public InstaceOne(@Named("one") Bean b1) {
            System.out.println(b1.name);
        }
    }

    public static class InstaceTwo implements A {

        @javax.inject.Inject
        public InstaceTwo(@Named("two") Bean b1) {
            System.out.println(b1.name);
        }
    }

}

Here, I am using annotatedWith to name my guice-handled instances. One of them corresponds to the String "one" and the other to "two", analogue to your example.

I can then, in my implementations of A have specific injections of these beans using the @Named annotation.

The result when running above code is:

beanOne
beanTwo

As you can see, it injected the correct instance of my bean into the right implementation.

Hope that helps,

Artur

pandaadb
  • 6,306
  • 2
  • 22
  • 41