-
Notifications
You must be signed in to change notification settings - Fork 1.7k
FrequentlyAskedQuestions
You need a binding annotation to identify your parameter. Create an annotation class that defines the parameter:
/**
* Annotates the URL of the foo server.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@BindingAnnotation
public @interface FooServerAddress {}
Bind the annotation to its value in your module:
public class FooModule extends AbstractModule {
private final String fooServerAddress;
/**
* @param fooServerAddress the URL of the foo server.
*/
public FooModule(String fooServerAddress) {
this.fooServerAddress = fooServerAddress;
}
@Override public void configure() {
bindConstant().annotatedWith(FooServerAddress.class).to(fooServerAddress);
...
}
}
Finally, inject it into your class:
public class FooClient {
@Inject
FooClient(@FooServerAddress String fooServerAddress) {
...
}
You may save some keystrokes by using Guice's built-in @Named
binding
annotation rather than creating your own.
Use Names.bindProperties() to create bindings for each of the properties in a configuration file.
You can't directly pass a parameter into an injected value. But you can use
Guice to create a Factory
, and use that factory to create your object.
public class Thing {
// note: no @Inject annotation here
private Thing(A a, B b) {
...
}
public static class Factory {
@Inject
public Factory(A a) { ... }
public Thing make(B b) { ... }
}
}
public class Example {
@Inject
public Example(Thing.Factory factory) { ... }
}
See AssistedInject, which can be used to remove the factory boilerplate.
This is commonly called the "robot legs" problem: How to create a robot with a
two Leg
objects, the left one injected with a LeftFoot
, and the right one
with a RightFoot
. But only one Leg
class that's reused in both contexts.
There's a PrivateModules solution that uses two separate private modules, a
@Left
one and an @Right
one. Each has a binding for the unannotated
Foot.class
and Leg.class
, and exposes a binding for the annotated
Leg.class
:
class LegModule extends PrivateModule {
private final Class<? extends Annotation> annotation;
LegModule(Class<? extends Annotation> annotation) {
this.annotation = annotation;
}
@Override protected void configure() {
bind(Leg.class).annotatedWith(annotation).to(Leg.class);
expose(Leg.class).annotatedWith(annotation);
bindFoot();
}
abstract void bindFoot();
}
public static void main(String[] args) {
Injector injector = Guice.createInjector(
new LegModule(Left.class) {
@Override void bindFoot() {
bind(Foot.class).toInstance(new Foot("leftie"));
}
},
new LegModule(Right.class) {
@Override void bindFoot() {
bind(Foot.class).toInstance(new Foot("righty"));
}
});
}
See also Alen Vrecko's more complete example.
Guice doesn't support this. However, you can inject a nested class (sometimes called a "static inner class"):
class Outer {
static class Nested {
...
}
}
You may need to inject a class with a parameterized type, like List<String>
:
class Example {
@Inject
void setList(List<String> list) {
...
}
}
You can use a
TypeLiteral
to create the binding. TypeLiteral
is a special class that allows you to
specify a full parameterized type.
@Override public void configure() {
bind(new TypeLiteral<List<String>>() {}).toInstance(new ArrayList<String>());
}
Alternately, you can use an @Provides method.
@Provides List<String> providesListOfString() {
return new ArrayList<String>();
}
Neither constructors nor @Provides
methods support optional injection. To
work-around this, you can create an inner class that holds the optional value:
class Car {
private final Engine engine;
private final AirConditioner airConditioner;
@Inject
public Car(Engine engine, AirConditionerHolder airConditionerHolder) {
this.engine = engine;
this.airConditioner = airConditionerHolder.value;
}
static class AirConditionerHolder {
@Inject(optional=true) AirConditioner value = new NoOpAirconditioner();
}
}
This also allows for a default value for the optional parameter.
In order to inject dependencies in an AOP MethodInterceptor
, use
requestInjection()
alongside the standard bindInterceptor()
call.
public class NotOnWeekendsModule extends AbstractModule {
protected void configure() {
MethodInterceptor interceptor = new WeekendBlocker();
requestInjection(interceptor);
bindInterceptor(any(), annotatedWith(NotOnWeekends.class), interceptor);
}
}
Another option is to use Binder.getProvider and pass the dependency in the constructor of the interceptor.
public class NotOnWeekendsModule extends AbstractModule {
protected void configure() {
bindInterceptor(any(),
annotatedWith(NotOnWeekends.class),
new WeekendBlocker(getProvider(Calendar.class)));
}
}
Please post to the google-guice discussion group.
-
User's Guide
-
Integration
-
Extensions
-
Internals
-
Releases
-
Community