Dependency Injection
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;
}
}
Core Guice Concepts
@Inject constructor
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.
Guice modules
The above Greeter class has two dependencies (declared in its constructor):
- A
String
object for the message to be printed - An
Integer
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";
}
}
Guice Injectors
@Inject
Greeter(@Message String message, @Count int count) {
this.message = message;
this.count = count;
}
A simple guice application
Mental Model
Guice is a map
These objects that your application needs are called dependencies.
- Guice key: a key in the map which is used to fetch a particular value from the map.
- Provider: a value in the map which is used to create objects for your application.
Guice Keys
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;
}
}