0
# Module System
1
2
The module system in Dagger defines how dependencies are constructed and provided to the dependency injection container. Modules contain provider methods and binding methods that tell Dagger how to create instances of various types.
3
4
## Capabilities
5
6
### @Module Annotation
7
8
Annotates classes that contribute bindings to the object graph. Modules can include other modules and declare subcomponents.
9
10
```java { .api }
11
/**
12
* Annotates classes that contribute bindings to the object graph
13
*/
14
@Target(ElementType.TYPE)
15
@Retention(RetentionPolicy.RUNTIME)
16
@interface Module {
17
/**
18
* Additional modules to include in this module
19
*/
20
Class<?>[] includes() default {};
21
22
/**
23
* Subcomponent classes that can be created from this module
24
*/
25
Class<?>[] subcomponents() default {};
26
}
27
```
28
29
**Usage Examples:**
30
31
```java
32
// Basic module
33
@Module
34
public class DatabaseModule {
35
@Provides
36
@Singleton
37
DatabaseConnection provideConnection() {
38
return new DatabaseConnection("localhost", 5432);
39
}
40
}
41
42
// Module including other modules
43
@Module(includes = {NetworkModule.class, CacheModule.class})
44
public class AppModule {
45
@Provides
46
AppService provideAppService(ApiClient client, Cache cache) {
47
return new AppService(client, cache);
48
}
49
}
50
51
// Module with subcomponents
52
@Module(subcomponents = UserSubcomponent.class)
53
public class ApplicationModule {
54
// Module bindings...
55
}
56
```
57
58
### @Provides Annotation
59
60
Annotates methods in modules to create provider method bindings. The method's return type is bound to the value returned by the method.
61
62
```java { .api }
63
/**
64
* Annotates methods in modules to create provider method bindings
65
*/
66
@Target(ElementType.METHOD)
67
@Retention(RetentionPolicy.RUNTIME)
68
@interface Provides {}
69
```
70
71
**Key Features:**
72
- Method return type becomes the bound type
73
- Method parameters are automatically injected by Dagger
74
- Supports scoping annotations (@Singleton, @Reusable, etc.)
75
- Supports qualifier annotations (@Named, custom qualifiers)
76
- Can return null if annotated with @Nullable
77
78
**Usage Examples:**
79
80
```java
81
@Module
82
public class NetworkModule {
83
// Simple provider
84
@Provides
85
@Singleton
86
OkHttpClient provideHttpClient() {
87
return new OkHttpClient.Builder()
88
.connectTimeout(30, TimeUnit.SECONDS)
89
.build();
90
}
91
92
// Provider with dependencies
93
@Provides
94
ApiService provideApiService(OkHttpClient client, Gson gson) {
95
return new Retrofit.Builder()
96
.baseUrl("https://api.example.com")
97
.client(client)
98
.addConverterFactory(GsonConverterFactory.create(gson))
99
.build()
100
.create(ApiService.class);
101
}
102
103
// Qualified provider
104
@Provides
105
@Named("api-key")
106
String provideApiKey() {
107
return BuildConfig.API_KEY;
108
}
109
110
// Nullable provider
111
@Provides
112
@Nullable
113
CacheConfig provideCacheConfig() {
114
return BuildConfig.DEBUG ? null : new CacheConfig();
115
}
116
}
117
```
118
119
### @Binds Annotation
120
121
Annotates abstract methods in modules for delegation bindings. More efficient than @Provides methods that just return an injected parameter.
122
123
```java { .api }
124
/**
125
* Annotates abstract methods in modules for delegation bindings
126
*/
127
@Target(ElementType.METHOD)
128
@Retention(RetentionPolicy.RUNTIME)
129
@interface Binds {}
130
```
131
132
**Key Features:**
133
- Must be abstract method in abstract module class
134
- Single parameter that is assignable to return type
135
- More efficient than equivalent @Provides method
136
- Supports scoping and qualification
137
- Works with multibindings (@IntoSet, @IntoMap)
138
139
**Usage Examples:**
140
141
```java
142
@Module
143
public abstract class RepositoryModule {
144
// Bind interface to implementation
145
@Binds
146
abstract UserRepository bindUserRepository(UserRepositoryImpl impl);
147
148
// Bind with qualifier
149
@Binds
150
@Named("local")
151
abstract DataSource bindLocalDataSource(LocalDataSource impl);
152
153
// Bind into set
154
@Binds
155
@IntoSet
156
abstract Validator bindEmailValidator(EmailValidator impl);
157
158
// Bind into map
159
@Binds
160
@IntoMap
161
@StringKey("user")
162
abstract Repository bindUserRepository(UserRepository impl);
163
164
// Can mix with @Provides in same module
165
@Provides
166
static Database provideDatabase() {
167
return Room.databaseBuilder(...)
168
.build();
169
}
170
}
171
```
172
173
### @BindsOptionalOf Annotation
174
175
Declares bindings for Optional containers of values that may or may not be present in the dependency graph.
176
177
```java { .api }
178
/**
179
* Annotates abstract methods that declare optional bindings
180
* @Beta This API is subject to incompatible changes
181
*/
182
@Target(ElementType.METHOD)
183
@Retention(RetentionPolicy.RUNTIME)
184
@interface BindsOptionalOf {}
185
```
186
187
**Key Features:**
188
- Must be abstract method with no parameters
189
- Returns Optional<T> if binding is present, Optional.empty() otherwise
190
- Supports Optional<Provider<T>>, Optional<Lazy<T>>, Optional<Provider<Lazy<T>>>
191
- Cannot bind @Nullable types to Optional<T> (compile error)
192
193
**Usage Examples:**
194
195
```java
196
@Module
197
public abstract class OptionalModule {
198
// Declare optional binding
199
@BindsOptionalOf
200
abstract Optional<FeatureFlag> optionalFeatureFlag();
201
202
// Optional provider
203
@BindsOptionalOf
204
abstract Optional<Provider<ExpensiveService>> optionalExpensiveService();
205
}
206
207
// Usage in injected class
208
public class FeatureService {
209
private final Optional<FeatureFlag> featureFlag;
210
211
@Inject
212
public FeatureService(Optional<FeatureFlag> featureFlag) {
213
this.featureFlag = featureFlag;
214
}
215
216
public boolean isFeatureEnabled() {
217
return featureFlag.map(FeatureFlag::isEnabled).orElse(false);
218
}
219
}
220
```
221
222
### Module Composition
223
224
Modules can include other modules to compose larger binding graphs.
225
226
```java
227
// Base modules
228
@Module
229
public class NetworkModule {
230
@Provides @Singleton
231
OkHttpClient provideHttpClient() { /* ... */ }
232
}
233
234
@Module
235
public class DatabaseModule {
236
@Provides @Singleton
237
Database provideDatabase() { /* ... */ }
238
}
239
240
// Composed module
241
@Module(includes = {NetworkModule.class, DatabaseModule.class})
242
public class AppModule {
243
@Provides
244
AppService provideAppService(OkHttpClient client, Database database) {
245
return new AppService(client, database);
246
}
247
}
248
```
249
250
### Static Provider Methods
251
252
Provider methods can be static for better performance when they don't need instance state.
253
254
```java
255
@Module
256
public abstract class UtilityModule {
257
@Provides
258
static Gson provideGson() {
259
return new GsonBuilder()
260
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
261
.create();
262
}
263
264
@Provides
265
static ExecutorService provideExecutorService() {
266
return Executors.newFixedThreadPool(4);
267
}
268
}
269
```
270
271
### Module Validation
272
273
Dagger performs compile-time validation of modules:
274
- All dependencies of provider methods must be satisfiable
275
- Abstract modules with @Binds methods cannot be instantiated directly
276
- Circular dependencies are detected and reported
277
- Missing bindings cause compilation errors
278
- Conflicting bindings (same type from multiple sources) cause errors
279
280
### Module Best Practices
281
282
**Granular Modules:**
283
```java
284
// Good: Specific responsibility
285
@Module
286
public class NetworkModule { /* ... */ }
287
288
@Module
289
public class DatabaseModule { /* ... */ }
290
291
// Avoid: Monolithic module
292
@Module
293
public class EverythingModule { /* ... */ }
294
```
295
296
**Prefer @Binds over @Provides:**
297
```java
298
// Preferred: More efficient
299
@Binds
300
abstract UserRepository bindUserRepository(UserRepositoryImpl impl);
301
302
// Less efficient
303
@Provides
304
UserRepository provideUserRepository(UserRepositoryImpl impl) {
305
return impl;
306
}
307
```