简体   繁体   中英

Google Guice Named vs Annotation

I was going through Google Guice documentation and read about UntargettedBinding . Basically there are two options

  1. @Named
  2. Binding annotation

My question is, which one is better?

With @Named I dont have to create boiler plates to use annotations but it comes at cost of less type safety. Annotation code looks more cleaner IMHO.

You specified the Pros and Cons of binding annotation in general as explained here .
Your statements are correct.

One more advantage of @Named is to bind for properties using Names.bindProperties. Where using binding annotation is irrelevant. See how to load properties

For UntargetBinding (which sound like it was the actual question) the documentation states two options

If you don't want to use binding annotation/@Named just declare the bind to the concrete class.
Eg

bind(MyConcreteClass.class);
bind(AnotherConcreteClass.class).in(Singleton.class);

You need to use binding annotation/@Named you must still add the target binding ie the " .toSometing " methods (to, toProvider, toContractor etc.)

For example:

public class TestUntargetBinding {

    @Test
    void testTargetBindingViaImplementBy() {
        final var injector = Guice.createInjector(new AbstractModule() {
            @Override
            public void configure() {
                bind(MyConcreteClass.class)
                        .annotatedWith(Names.named("100"))
                        .toProvider(() -> new MyConcreteClass(100));
                bind(MyConcreteClass.class)
                        .annotatedWith(Names.named("200"))
                        .toProvider(() -> new MyConcreteClass(200));

            }
        });
        //imagine a class with a constructor
        // @Inject
        // SomeClass(@Named("100) MyConcreteClass myConcreteClass1){...}
        final var myConcreteClass1 = injector.getInstance(Key.get(MyConcreteClass.class, Names.named("100")));
        final var myConcreteClass2 = injector.getInstance(Key.get(MyConcreteClass.class, Names.named("200")));

        assertThat(myConcreteClass1.doSomething(), Is.is(100));
        assertThat(myConcreteClass2.doSomething(), Is.is(200));

    }

    static class MyConcreteClass {
        private int i;

        public MyConcreteClass(int i) {
            this.i = i;
        }

        public int doSomething() {
            return i;
        }
    }
}

Guice will not know witch class to bind the name/annotation to unless you will specify the " toProvider "

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM