Guice provides two variations of so-called binding annotations, which seem to really break down to class- and instance-level annotations:
“Class-level”:
bind(Service.class).annotatedWith(Red.class).to(RedServiceImpl.class);
@Red
public class SomeService implements Service { ... }
Service redSvc = injector.getInstance(SomeService.class);
“Instance-level”:
bind(Service.class).annotatedWith(Names.named("Blue").to(BlueServiceImpl.class);
@Blue blueSvc = injector.getInstance(Service.class);
When is one method preferential over the other? It seems that class-level annotations are more absolute/inflexible than instance-level. Pros/cons/caveats/pitfalls of either method?
I’m not sure I understand your question. Your use of binding annotations is irregular. You wouldn’t typically annotate a local variable or a class, but rather fields and parameters.
Your first code example will cause the injector to return SomeService, but not because of your annotation or your binding, but because SomeService is a concrete implementation. Had you asked for this instead:
You will get an error:
Your second example is also incorrect. If you use
Namesto define a binding, you must use@Namedto access that binding. Using@Bluewould cause a compiler error. The correct usage would be@Named(value="Blue").The common best practice for a binding annotation is this:
In that case, both of these would be compile errors: