Guice

extending:

http://developer.vz.net/2012/02/08/extending-guice-2/
http://forkbomb-blog.de/2012/slf4j-logger-injection-with-guice
https://github.com/google/guice/wiki/CustomInjections
https://spin.atomicobject.com/2012/01/13/the-guava-eventbus-on-guice/

annotations with value

http://stackoverflow.com/questions/28549549/guice-inject-based-on-annotation-value
https://github.com/google/guice/wiki/BindingAnnotations

public class MyAnnotations {
  @BindingAnnotation
  @Retention(RetentionPolicy.RUNTIME)
  @Target({ ElementType.PARAMETER, ElementType.FIELD})
  public @interface AutoConfig {
    String value() default "abc";
  }
}
public class AutoConfigImpl implements MyAnnotations.AutoConfig{

  String value; 
  public AutoConfigImpl(String value) {
    this.value = value;
  }

  @Override
  public Class<? extends Annotation> annotationType() {
    return MyAnnotations.AutoConfig.class;
  }

  @Override
  public String value() {
    return value;
  }

  public int hashCode() {
    return (127 * "value".hashCode()) ^ value.hashCode();
  }

  public boolean equals(Object o) {
    if (!(o instanceof MyAnnotations.AutoConfig)) {
      return false;
    }

    MyAnnotations.AutoConfig other = (MyAnnotations.AutoConfig) o;
    return value.equals(other.value());
  }

  private static final long serialVersionUID = 0; 
}
public class UseHello {
  final Hello hello;

  @Inject
  UseHello(@MyAnnotations.AutoConfig(value="def") Hello hello) {
    this.hello = hello;
  }

  public Hello getHello() {
    return hello;
  }
}
Injector injector = Guice.createInjector(new AbstractModule() {

        @Override
        protected void configure() {
          bind(Hello.class).annotatedWith(new AutoConfigImpl("def")).to(Hello1.class);
          bind(Hello.class).to(Hello2.class);
          bind(Hello.class).annotatedWith(new AutoConfigImpl("abc")).to(Hello3.class);
        }        
      });

      System.out.println("hello is:" + injector.getInstance(UseHello.class).getHello().getMessage());  /// hello1
      System.out.println("hello self is:" + injector.getInstance(Hello.class).getMessage()); // hello2
      System.out.println("hello specificis:" + 
         injector.getInstance(Key.get(Hello.class, new AutoConfigImpl("abc"))).getMessage()); // hello3

if UseHello 's annotation is default, then injector.getInstance(UseHello.class).getHello().getMessage()) will be Hello3 as default value if "abc".

pub?w=960&amp;h=720

MiniGuice

A)
When a module is loaded, Guice basically create bindings from
Key.of(Bar.class, BarAnnotation.class) to a anonymous Provider, and it is put into: Map<Key, Provider<?» providersMap

B)
When Guice is bootstrapped in Jit for requiredKey(Foo.class) as the only initial element in requiredKeysQueue:

1) loop over requiredKey in the requiredKeysQueue.
1.1) for class of Foo (required key's type), if it is not in providersMap's key set yet, Guice will use reflection to gather fields, constructor.
1.1.1) Every field has an associated required key(FieldClass, annotation). It is put into Queue<Key> requiredKeysQueue.

1.1.2) for constructor, it examines injected constructor's parameters(constructor.getGenericParameterTypes(), constructor.getParameterAnnotations() ).
each parameter will have an associated required key(Parameter.class, annotation), which is put into requiredKeysQueue.

==> notice Provider<Bar> parameter is specially handled,
the required key is Key( xx.getActualTypeArguments()[0], key.annotation), where xx = constructor.getGenericParameterType = ParameterizedType.
for normal class, Parameter.class = Hello.class = constructor.getGenericParameterType

1.1.3) and a provider for the constructor on key(Foo.class, null_annotation) is also created and input into providersMap.

repeat the steps in step 1 until requiredKeysQueue is empty.

C)
for every key in providersMap, a provider's provider is also inserted. the new entry has key:
new ProviderType(javax.inject.Provider.class, key.type), key.annotation)

D)
then when it is required to create an instance of Foo.class,
1.1) it calls Foo constructor, where each parameter's key is searched in providersMap to create the parameter value.
1.2) each field is also injected by searching providersMap with field's key.

Notice of

@Inject Foo(Provide<Bar> bar) { // constructor
   }

- in step B.1.1.2). the Key inserted into requiredKeysQueue is Key(Bar.class). not Key(Provider<Bar>.class).
- in step D 1.1), the parameter key will be ParameterizedType<Bar> and it is used to search providersMap , as
- ProviderType implements ParameterizedType
- ProviderType overrides getRawType to return Provider.class instead of ProviderType .class
- based on hashCode and equals of ProviderType. ParameterizedType<Bar> will match ProviderType instance key.
thus, the Provider's provider created in step C) is returned.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License