or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assisted-injection.mdcomponent-framework.mdindex.mdmodule-system.mdmultibindings.mdutility-types.md

module-system.mddocs/

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

```