or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

annotations.mdapplication-context.mdbean-definition.mdbean-factory.mdbean-processing.mdbean-providers.mdenvironment-config.mdevents.mdexceptions.mdindex.mdscoping.md

bean-factory.mddocs/

0

# Bean Factory and Advanced Configuration

1

2

The bean factory pattern provides programmatic bean creation, advanced configuration building, and runtime bean registration capabilities. This enables dynamic bean creation and complex configuration scenarios.

3

4

## Factory Pattern

5

6

### @Factory Annotation

7

8

Marks a class as a bean factory for creating and configuring other beans.

9

10

```java { .api }

11

@Target({TYPE})

12

@Retention(RUNTIME)

13

@Documented

14

public @interface Factory {

15

}

16

```

17

18

### @Bean Annotation

19

20

Marks methods within factory classes that produce bean instances.

21

22

```java { .api }

23

@Target({METHOD})

24

@Retention(RUNTIME)

25

@Documented

26

public @interface Bean {

27

/**

28

* Bean name override

29

*/

30

String named() default "";

31

32

/**

33

* Pre-destroy method name

34

*/

35

String preDestroy() default "";

36

}

37

```

38

39

**Usage Examples:**

40

41

```java

42

import io.micronaut.context.annotation.Factory;

43

import io.micronaut.context.annotation.Bean;

44

import jakarta.inject.Singleton;

45

46

@Factory

47

public class DatabaseConfigurationFactory {

48

49

@Bean

50

@Singleton

51

public DataSource primaryDataSource() {

52

HikariConfig config = new HikariConfig();

53

config.setJdbcUrl("jdbc:h2:mem:testdb");

54

config.setUsername("sa");

55

config.setPassword("");

56

config.setMaximumPoolSize(10);

57

return new HikariDataSource(config);

58

}

59

60

@Bean

61

@Singleton

62

@Named("readonly")

63

public DataSource readOnlyDataSource() {

64

HikariConfig config = new HikariConfig();

65

config.setJdbcUrl("jdbc:h2:mem:readonly");

66

config.setUsername("reader");

67

config.setReadOnly(true);

68

return new HikariDataSource(config);

69

}

70

71

@Bean

72

@Singleton

73

public EntityManagerFactory entityManagerFactory(DataSource dataSource) {

74

LocalContainerEntityManagerFactoryBean factory =

75

new LocalContainerEntityManagerFactoryBean();

76

factory.setDataSource(dataSource);

77

factory.setPackagesToScan("com.example.entities");

78

factory.afterPropertiesSet();

79

return factory.getObject();

80

}

81

}

82

```

83

84

### Complex Factory Configuration

85

86

```java

87

@Factory

88

public class HttpClientFactory {

89

90

@Value("${http.timeout:30s}")

91

private Duration timeout;

92

93

@Value("${http.max-connections:100}")

94

private int maxConnections;

95

96

@Bean

97

@Singleton

98

public HttpClient defaultHttpClient() {

99

return HttpClient.newBuilder()

100

.connectTimeout(timeout)

101

.build();

102

}

103

104

@Bean

105

@Singleton

106

@Named("secure")

107

public HttpClient secureHttpClient() {

108

SSLContext sslContext = createCustomSSLContext();

109

return HttpClient.newBuilder()

110

.connectTimeout(timeout)

111

.sslContext(sslContext)

112

.build();

113

}

114

115

@Bean

116

@Singleton

117

public ConnectionPool connectionPool() {

118

return new ConnectionPool.Builder()

119

.maxConnections(maxConnections)

120

.keepAliveDuration(5, TimeUnit.MINUTES)

121

.build();

122

}

123

124

private SSLContext createCustomSSLContext() {

125

// Custom SSL context creation logic

126

return SSLContext.getDefault();

127

}

128

}

129

```

130

131

## Runtime Bean Registration

132

133

### RuntimeBeanDefinition

134

135

Interface for creating bean definitions programmatically at runtime.

136

137

```java { .api }

138

/**

139

* Interface for runtime bean definition creation

140

* @param <T> The bean type

141

*/

142

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

143

/**

144

* Create a runtime bean definition for the given type

145

* @param type The bean type

146

* @return RuntimeBeanDefinition instance

147

*/

148

static <T> RuntimeBeanDefinition<T> of(Class<T> type);

149

150

/**

151

* Create a runtime bean definition with custom factory

152

* @param type The bean type

153

* @param factory The bean factory

154

* @return RuntimeBeanDefinition instance

155

*/

156

static <T> RuntimeBeanDefinition<T> of(Class<T> type, BeanFactory<T> factory);

157

158

/**

159

* Create a runtime bean definition for a singleton instance

160

* @param instance The singleton instance

161

* @return RuntimeBeanDefinition instance

162

*/

163

static <T> RuntimeBeanDefinition<T> of(T instance);

164

165

/**

166

* Add a qualifier to this bean definition

167

* @param qualifier The qualifier

168

* @return This bean definition

169

*/

170

RuntimeBeanDefinition<T> qualifier(Class<? extends Annotation> qualifier);

171

172

/**

173

* Mark this bean as singleton

174

* @return This bean definition

175

*/

176

RuntimeBeanDefinition<T> singleton();

177

178

/**

179

* Mark this bean as prototype

180

* @return This bean definition

181

*/

182

RuntimeBeanDefinition<T> prototype();

183

}

184

```

185

186

**Usage Examples:**

187

188

```java

189

import io.micronaut.context.RuntimeBeanDefinition;

190

import io.micronaut.context.ApplicationContext;

191

192

public class DynamicBeanRegistration {

193

194

public void registerDynamicBeans(ApplicationContext context) {

195

// Register a simple singleton bean

196

RuntimeBeanDefinition<MyService> serviceDef =

197

RuntimeBeanDefinition.of(MyService.class).singleton();

198

context.registerBeanDefinition(serviceDef);

199

200

// Register bean with custom factory

201

RuntimeBeanDefinition<ComplexService> complexDef =

202

RuntimeBeanDefinition.of(ComplexService.class, (resolutionContext, beanContext) -> {

203

ComplexService service = new ComplexService();

204

service.configure(beanContext.getBean(Configuration.class));

205

return service;

206

}).singleton();

207

context.registerBeanDefinition(complexDef);

208

209

// Register singleton instance

210

MyConfiguration config = new MyConfiguration();

211

config.setProperty("value", "runtime-configured");

212

RuntimeBeanDefinition<MyConfiguration> configDef =

213

RuntimeBeanDefinition.of(config);

214

context.registerBeanDefinition(configDef);

215

216

// Register with qualifier

217

RuntimeBeanDefinition<DatabaseService> dbDef =

218

RuntimeBeanDefinition.of(DatabaseService.class)

219

.qualifier(Named.class)

220

.singleton();

221

context.registerBeanDefinition(dbDef);

222

}

223

}

224

```

225

226

## Advanced Configuration Patterns

227

228

### @ConfigurationBuilder

229

230

Enables configuration of complex objects through builder pattern integration.

231

232

```java { .api }

233

@Target({FIELD, METHOD, PARAMETER})

234

@Retention(RUNTIME)

235

@Documented

236

public @interface ConfigurationBuilder {

237

/**

238

* Property prefix for configuration values

239

*/

240

String value() default "";

241

242

/**

243

* Configuration prefix for nested configuration

244

*/

245

String configurationPrefix() default "";

246

247

/**

248

* Method prefixes to include

249

*/

250

String[] includes() default {};

251

252

/**

253

* Method prefixes to exclude

254

*/

255

String[] excludes() default {};

256

257

/**

258

* Whether to allow zero args methods

259

*/

260

boolean allowZeroArgs() default false;

261

}

262

```

263

264

**Usage Examples:**

265

266

```java

267

import io.micronaut.context.annotation.ConfigurationProperties;

268

import io.micronaut.context.annotation.ConfigurationBuilder;

269

270

@ConfigurationProperties("datasource")

271

public class DataSourceConfig {

272

273

@ConfigurationBuilder(configurationPrefix = "hikari")

274

private final HikariConfig hikariConfig = new HikariConfig();

275

276

@ConfigurationBuilder(configurationPrefix = "connection-pool")

277

private final ConnectionPoolSettings poolSettings = new ConnectionPoolSettings();

278

279

public HikariConfig getHikariConfig() {

280

return hikariConfig;

281

}

282

283

public ConnectionPoolSettings getPoolSettings() {

284

return poolSettings;

285

}

286

}

287

288

// Enables configuration like:

289

// datasource.hikari.maximum-pool-size=20

290

// datasource.hikari.minimum-idle=5

291

// datasource.connection-pool.max-lifetime=1800000

292

```

293

294

### @EachBean and @EachProperty

295

296

Dynamic bean creation based on configuration entries.

297

298

```java { .api }

299

@Target({TYPE})

300

@Retention(RUNTIME)

301

@Documented

302

public @interface EachBean {

303

/**

304

* The bean type to iterate over

305

*/

306

Class<?> value();

307

}

308

309

@Target({TYPE})

310

@Retention(RUNTIME)

311

@Documented

312

public @interface EachProperty {

313

/**

314

* The property prefix to iterate over

315

*/

316

String value();

317

318

/**

319

* Primary bean marker

320

*/

321

boolean primary() default false;

322

}

323

```

324

325

**Usage Examples:**

326

327

```java

328

// Configuration-driven bean creation

329

@EachProperty("databases")

330

@ConfigurationProperties("databases")

331

public class DatabaseConfig {

332

private String url;

333

private String username;

334

private String password;

335

336

// getters and setters

337

}

338

339

@EachBean(DatabaseConfig.class)

340

@Singleton

341

public class DatabaseService {

342

343

private final DatabaseConfig config;

344

345

public DatabaseService(DatabaseConfig config) {

346

this.config = config;

347

}

348

349

public Connection getConnection() {

350

return DriverManager.getConnection(

351

config.getUrl(),

352

config.getUsername(),

353

config.getPassword()

354

);

355

}

356

}

357

358

// Configuration example:

359

// databases.primary.url=jdbc:postgresql://localhost/primary

360

// databases.primary.username=user1

361

// databases.secondary.url=jdbc:postgresql://localhost/secondary

362

// databases.secondary.username=user2

363

```

364

365

## Bean Lifecycle and Management

366

367

### BeanFactory Interface

368

369

Core interface for custom bean creation logic.

370

371

```java { .api }

372

/**

373

* Factory interface for creating bean instances

374

* @param <T> The bean type

375

*/

376

public interface BeanFactory<T> {

377

/**

378

* Build a bean instance

379

* @param resolutionContext The resolution context

380

* @param context The bean context

381

* @param definition The bean definition

382

* @return Bean instance

383

*/

384

T build(BeanResolutionContext resolutionContext, BeanContext context, BeanDefinition<T> definition);

385

386

/**

387

* Build a bean instance with additional arguments

388

* @param resolutionContext The resolution context

389

* @param context The bean context

390

* @param definition The bean definition

391

* @param args Additional constructor arguments

392

* @return Bean instance

393

*/

394

default T build(BeanResolutionContext resolutionContext, BeanContext context,

395

BeanDefinition<T> definition, Object... args) {

396

return build(resolutionContext, context, definition);

397

}

398

}

399

```

400

401

### Bean Registration and Management

402

403

```java { .api }

404

public interface BeanDefinitionRegistry {

405

/**

406

* Register a bean definition

407

* @param beanDefinition The bean definition to register

408

* @return The bean definition

409

*/

410

<T> BeanDefinition<T> registerBeanDefinition(BeanDefinition<T> beanDefinition);

411

412

/**

413

* Register a singleton bean instance

414

* @param type The bean type

415

* @param singleton The singleton instance

416

* @return The application context

417

*/

418

<T> ApplicationContext registerSingleton(Class<T> type, T singleton);

419

420

/**

421

* Register a singleton bean with qualifier

422

* @param type The bean type

423

* @param singleton The singleton instance

424

* @param qualifier The qualifier

425

* @return The application context

426

*/

427

<T> ApplicationContext registerSingleton(Class<T> type, T singleton, Qualifier<T> qualifier);

428

}

429

```

430

431

## Types

432

433

### Factory-related Types

434

435

```java { .api }

436

public interface BeanCreationContext<T> extends BeanResolutionContext {

437

BeanDefinition<T> definition();

438

CreatedBean<T> create() throws BeanCreationException;

439

}

440

441

public interface CreatedBean<T> {

442

BeanDefinition<T> definition();

443

T bean();

444

445

default void inject(BeanResolutionContext resolutionContext, BeanContext context) {

446

// Perform injection on the created bean

447

}

448

}

449

450

public class BeanCreationException extends BeanContextException {

451

public BeanCreationException(String message);

452

public BeanCreationException(String message, Throwable cause);

453

public BeanCreationException(BeanDefinition<?> definition, String message);

454

public BeanCreationException(BeanDefinition<?> definition, String message, Throwable cause);

455

456

public Optional<BeanDefinition<?>> getBeanDefinition();

457

}

458

```