|
FrequentlyAskedQuestions
Frequently Asked QuestionsHow do I inject configuration parameters?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 value in your module: public class FooModule {
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. How do I load configuration properties?Use Names.bindProperties() to create bindings for each of the properties in a configuration file. How do I pass a parameter when creating an object via Guice?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. How do I build two similar but slightly different trees of objects?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. It 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. How can I inject an inner class?Guice doesn't support this. However, you can inject a nested class (sometimes called a "static inner class"): class Outer {
static class Nested {
...
}
}How to inject class with generic type?You may need to inject a class with a parameterized type, like List<String>: class Example {
@Inject
void setList(List<String> list) {
...
}
}You need to use 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>());
}How can I inject optional parameters into a constructor?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. How do I inject a method interceptor?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);
}
}How can I get other questions answered?Please post to the google-guice discussion group. |
Sign in to add a comment
How can I use @Assisted with Strings (or other distinct parameters of the same type)?
If you use AssistedInject and declare two String parameters, you may have seen an error of the form
To use multiple parameters of the same type, use a named @Assisted annotation with a String value to disambiguate the parameters.
See com.google.inject.assistedinject.FactoryProvider? for documentation and examples.
@Leigh: You need to give the @AssistedAnnotation? a name. Use the same name in both the factory method and in the constructor, and you're golden.
public interface Factory { Person create(@Assisted("givenName") String givenName, @Assisted("surname") String surname); }I don't think the List<String> example works. Every injection of List<String> will be bound to the same ArrayList? (since toInstance() implicitly creates a singleton). This is probably not what the user intended.