Dependency injection is a design pattern wherein classes declare their dependencies as arguments instead of creating those dependencies directly.
class Foo {
private Database database; // We need a Database to do some work
// The database comes from somewhere else. Where? That's not my job, that's
// the job of whoever constructs me: they can choose which database to use.
Foo(Database database) {
this.database = database;
}
}
Java class constructors that are annotated with @Inject can be called by Guice through a process called constructor injection, during which the constructors’ arguments will be created and provided by Guice.
标记了 @Inject 的构造方法,Guice 会自动装配其参数。
class Greeter {
private final String message;
private final int count;
// Greeter declares that it needs a string message and an integer
// representing the number of time the message to be printed.
// The @Inject annotation marks this constructor as eligible to be used by
// Guice.
@Inject
Greeter(@Message String message, @Count int count) {
this.message = message;
this.count = count;
}
void sayHello() {
for (int i=0; i < count; i++) {
System.out.println(message);
}
}
}
The Greeter
class’s constructor arguments are its dependencies
and applications use Module
to tell Guice how to satisfy those dependencies.
The above Greeter class has two dependencies (declared in its constructor):
String
object for the message to be printedInteger
object for the number of times to print the message/**
* Guice module that provides bindings for message and count used in
* {@link Greeter}.
*/
import com.google.inject.Provides;
class DemoModule extends AbstractModule {
@Provides
@Count
static Integer provideCount() {
return 3;
}
@Provides
@Message
static String provideMessage() {
return "hello world";
}
}
@Inject
Greeter(@Message String message, @Count int count) {
this.message = message;
this.count = count;
}
These objects that your application needs are called dependencies.
Guice uses Key to identify a dependency that can be resolved using the “Guice map”.
@Message String --> Key<String>
@Count int --> Key<Integer>
// Identifies a dependency that is an instance of String.
Key<String> databaseKey = Key.get(String.class);
However, applications often have dependencies that are of the same type:
final class MultilingualGreeter {
private String englishGreeting;
private String spanishGreeting;
// 两个都是 String 类型
MultilingualGreeter(String englishGreeting, String spanishGreeting) {
this.englishGreeting = englishGreeting;
this.spanishGreeting = spanishGreeting;
}
}