or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

aop.mdconfiguration.mddependency-injection.mdfunctions.mdhttp-client.mdhttp-server.mdindex.mdmanagement.mdmessaging.mdreactive.mdretry.mdscheduling.mdwebsocket.md

dependency-injection.mddocs/

0

# Dependency Injection

1

2

Micronaut's dependency injection system uses compile-time processing to eliminate reflection and provide fast application startup. It supports the full Jakarta Inject specification plus additional features for modern application development.

3

4

## Capabilities

5

6

### Bean Declaration

7

8

Define beans using standard Jakarta Inject annotations or Micronaut-specific annotations.

9

10

```java { .api }

11

/**

12

* Mark a class as a singleton bean

13

*/

14

@Singleton

15

public class UserService {

16

private final UserRepository repository;

17

18

public UserService(UserRepository repository) {

19

this.repository = repository;

20

}

21

}

22

23

/**

24

* Create beans using factory methods

25

*/

26

@Factory

27

public class DatabaseFactory {

28

29

@Bean

30

@Singleton

31

public DataSource dataSource() {

32

return new HikariDataSource();

33

}

34

}

35

36

/**

37

* Prototype scope (new instance each time)

38

*/

39

@Prototype

40

public class RequestHandler {

41

// New instance for each injection

42

}

43

```

44

45

### Dependency Injection

46

47

Inject dependencies through constructor, field, or method injection.

48

49

```java { .api }

50

/**

51

* Constructor injection (recommended)

52

*/

53

@Singleton

54

public class OrderService {

55

private final PaymentService paymentService;

56

private final InventoryService inventoryService;

57

58

public OrderService(PaymentService paymentService,

59

InventoryService inventoryService) {

60

this.paymentService = paymentService;

61

this.inventoryService = inventoryService;

62

}

63

}

64

65

/**

66

* Field injection

67

*/

68

@Singleton

69

public class NotificationService {

70

@Inject

71

private EmailService emailService;

72

}

73

74

/**

75

* Method injection

76

*/

77

@Singleton

78

public class ConfigService {

79

private DatabaseConfig config;

80

81

@Inject

82

public void setDatabaseConfig(DatabaseConfig config) {

83

this.config = config;

84

}

85

}

86

```

87

88

### Qualifiers

89

90

Use qualifiers to distinguish between multiple implementations of the same interface.

91

92

```java { .api }

93

/**

94

* Named qualifier

95

*/

96

@Singleton

97

@Named("mysql")

98

public class MySqlRepository implements Repository {

99

// MySQL implementation

100

}

101

102

@Singleton

103

@Named("postgres")

104

public class PostgresRepository implements Repository {

105

// PostgreSQL implementation

106

}

107

108

/**

109

* Inject specific implementation

110

*/

111

@Singleton

112

public class DataService {

113

private final Repository repository;

114

115

public DataService(@Named("mysql") Repository repository) {

116

this.repository = repository;

117

}

118

}

119

120

/**

121

* Custom qualifiers

122

*/

123

@Qualifier

124

@Retention(RetentionPolicy.RUNTIME)

125

public @interface Database {

126

String value();

127

}

128

129

@Singleton

130

@Database("primary")

131

public class PrimaryDatabase implements DatabaseService {

132

// Primary database implementation

133

}

134

```

135

136

### Bean Scopes

137

138

Control bean lifecycle with built-in and custom scopes.

139

140

```java { .api }

141

/**

142

* Built-in scopes

143

*/

144

@Singleton // Single instance per application

145

@Prototype // New instance each time

146

@RequestScope // One instance per HTTP request

147

@ThreadLocal // One instance per thread

148

149

/**

150

* Custom scope example

151

*/

152

@Scope

153

@Retention(RetentionPolicy.RUNTIME)

154

public @interface TenantScope {

155

}

156

157

@TenantScope

158

public class TenantService {

159

// One instance per tenant

160

}

161

```

162

163

### Conditional Beans

164

165

Create beans conditionally based on configuration, environment, or other factors.

166

167

```java { .api }

168

/**

169

* Conditional on property value

170

*/

171

@Singleton

172

@Requires(property = "cache.enabled", value = "true")

173

public class CacheService {

174

// Only created if cache.enabled=true

175

}

176

177

/**

178

* Conditional on missing bean

179

*/

180

@Singleton

181

@Requires(missingBeans = CustomMetricsService.class)

182

public class DefaultMetricsService implements MetricsService {

183

// Only created if CustomMetricsService not present

184

}

185

186

/**

187

* Conditional on environment

188

*/

189

@Singleton

190

@Requires(env = Environment.DEVELOPMENT)

191

public class DevelopmentDataLoader {

192

// Only in development environment

193

}

194

195

/**

196

* Custom condition

197

*/

198

@Singleton

199

@Requires(condition = DatabaseAvailableCondition.class)

200

public class DatabaseService {

201

// Custom condition logic

202

}

203

```

204

205

### Bean Factories

206

207

Create complex beans using factory classes and methods.

208

209

```java { .api }

210

/**

211

* Factory class for complex bean creation

212

*/

213

@Factory

214

public class HttpClientFactory {

215

216

@Bean

217

@Singleton

218

@Named("api-client")

219

public HttpClient createApiClient(@Value("${api.base-url}") String baseUrl) {

220

return HttpClient.create(URL.of(baseUrl))

221

.configuration(config -> {

222

config.readTimeout(Duration.ofSeconds(30));

223

config.connectTimeout(Duration.ofSeconds(10));

224

});

225

}

226

227

@Bean

228

@Singleton

229

@Named("auth-client")

230

public HttpClient createAuthClient(@Value("${auth.url}") String authUrl) {

231

return HttpClient.create(URL.of(authUrl));

232

}

233

}

234

235

/**

236

* Parameterized factory for creating multiple similar beans

237

*/

238

@EachProperty("databases")

239

public class DatabaseFactory {

240

private String name;

241

private String url;

242

private String driver;

243

244

@Bean

245

@Singleton

246

public DataSource dataSource() {

247

return DataSourceBuilder.create()

248

.url(url)

249

.driverClassName(driver)

250

.build();

251

}

252

253

// getters and setters

254

}

255

```

256

257

### Bean Validation

258

259

Validate bean properties during creation using Jakarta Bean Validation.

260

261

```java { .api }

262

/**

263

* Bean with validation constraints

264

*/

265

@Singleton

266

public class UserService {

267

268

public User createUser(@Valid @NotNull CreateUserRequest request) {

269

// Method parameter validation

270

return new User(request.getName(), request.getEmail());

271

}

272

}

273

274

/**

275

* Configuration bean with validation

276

*/

277

@ConfigurationProperties("app")

278

public class AppConfiguration {

279

280

@NotBlank

281

private String name;

282

283

@Min(1)

284

@Max(65535)

285

private int port;

286

287

@Email

288

private String adminEmail;

289

290

// getters and setters with validation

291

}

292

```

293

294

### Bean Events

295

296

Listen to bean lifecycle events and publish custom events.

297

298

```java { .api }

299

/**

300

* Bean lifecycle events

301

*/

302

@Singleton

303

public class ServiceInitializer {

304

305

@EventListener

306

public void onStartup(StartupEvent event) {

307

// Application startup logic

308

}

309

310

@EventListener

311

public void onShutdown(ShutdownEvent event) {

312

// Cleanup logic

313

}

314

315

@EventListener

316

public void onBeanCreated(BeanCreatedEvent<DataSource> event) {

317

// React to DataSource bean creation

318

DataSource dataSource = event.getBean();

319

// Initialize connection pool, etc.

320

}

321

}

322

323

/**

324

* Custom event publishing

325

*/

326

@Singleton

327

public class OrderService {

328

private final ApplicationEventPublisher eventPublisher;

329

330

public OrderService(ApplicationEventPublisher eventPublisher) {

331

this.eventPublisher = eventPublisher;

332

}

333

334

public void processOrder(Order order) {

335

// Process order

336

eventPublisher.publishEvent(new OrderProcessedEvent(order));

337

}

338

}

339

```

340

341

### Bean Introspection

342

343

Access bean metadata at runtime without reflection.

344

345

```java { .api }

346

/**

347

* Enable introspection for a class

348

*/

349

@Introspected

350

public class Person {

351

private String firstName;

352

private String lastName;

353

private int age;

354

355

// constructors, getters, setters

356

}

357

358

/**

359

* Use introspection to access bean metadata

360

*/

361

@Singleton

362

public class ObjectMapper {

363

364

public Map<String, Object> toMap(Object obj) {

365

BeanIntrospection<Object> introspection =

366

BeanIntrospection.getIntrospection(obj.getClass());

367

368

Map<String, Object> map = new HashMap<>();

369

for (BeanProperty<Object, Object> property : introspection.getBeanProperties()) {

370

Object value = property.get(obj);

371

map.put(property.getName(), value);

372

}

373

return map;

374

}

375

}

376

```

377

378

## Types

379

380

```java { .api }

381

// Core DI interfaces

382

public interface BeanContext extends BeanLocator, LifeCycle<BeanContext> {

383

<T> T getBean(Class<T> beanType);

384

<T> T getBean(Class<T> beanType, Qualifier<T> qualifier);

385

<T> Optional<T> findBean(Class<T> beanType);

386

<T> Collection<T> getBeansOfType(Class<T> beanType);

387

<T> Stream<T> streamOfType(Class<T> beanType);

388

}

389

390

public interface BeanDefinition<T> extends BeanType<T> {

391

Class<T> getBeanType();

392

Optional<Class<?>> getDeclaringType();

393

boolean isEnabled(BeanContext context);

394

boolean isSingleton();

395

boolean isConfigurationProperties();

396

List<Argument<?>> getRequiredArguments();

397

}

398

399

public interface ApplicationContext extends BeanContext, LifeCycle<ApplicationContext> {

400

Environment getEnvironment();

401

ConversionService getConversionService();

402

void publishEvent(Object event);

403

static ApplicationContext build();

404

static ApplicationContext run();

405

}

406

407

// Bean introspection

408

public interface BeanIntrospection<T> {

409

Class<T> getBeanType();

410

Collection<BeanProperty<T, Object>> getBeanProperties();

411

Collection<BeanMethod<T, Object>> getBeanMethods();

412

T instantiate(Object... args);

413

static <T> BeanIntrospection<T> getIntrospection(Class<T> type);

414

}

415

416

public interface BeanProperty<B, T> {

417

Class<T> getType();

418

String getName();

419

T get(B bean);

420

void set(B bean, T value);

421

boolean isReadOnly();

422

boolean isWriteOnly();

423

}

424

425

// Injection points

426

public interface InjectionPoint<T> {

427

BeanDefinition<?> getDeclaringBean();

428

Class<T> getType();

429

Optional<String> getName();

430

AnnotationMetadata getAnnotationMetadata();

431

}

432

433

public interface FieldInjectionPoint<B, T> extends InjectionPoint<T> {

434

Field getField();

435

void set(B instance, T value);

436

}

437

438

public interface MethodInjectionPoint<B, T> extends InjectionPoint<T> {

439

Method getMethod();

440

T invoke(B instance, Object... args);

441

}

442

```