-
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