0
# Bean Definition and Injection
1
2
Bean definitions contain compile-time metadata about beans including their type, dependencies, injection points, and lifecycle methods. The Micronaut framework uses this information to perform dependency injection at runtime without reflection.
3
4
## Core Interfaces
5
6
### BeanDefinition
7
8
Represents metadata about a bean including its type, dependencies, and injection points.
9
10
```java { .api }
11
public interface BeanDefinition<T> extends BeanType<T> {
12
Class<T> getBeanType();
13
Optional<Class<?>> getDeclaringType();
14
List<Argument<?>> getConstructorArguments();
15
Collection<MethodInjectionPoint<T, ?>> getInjectedMethods();
16
Collection<FieldInjectionPoint<T, ?>> getInjectedFields();
17
Collection<ExecutableMethod<T, ?>> getExecutableMethods();
18
Optional<Method> getPostConstructMethod();
19
Optional<Method> getPreDestroyMethod();
20
boolean isAbstract();
21
boolean isSingleton();
22
boolean isConfigurationProperties();
23
T instantiate(BeanResolutionContext resolutionContext, BeanContext context);
24
T instantiate(BeanResolutionContext resolutionContext, BeanContext context, Object... args);
25
}
26
```
27
28
### BeanFactory
29
30
Factory interface for creating bean instances.
31
32
```java { .api }
33
public interface BeanFactory<T> {
34
T build(BeanResolutionContext resolutionContext, BeanContext context, BeanDefinition<T> definition);
35
T build(BeanResolutionContext resolutionContext, BeanContext context, BeanDefinition<T> definition, Object... args);
36
}
37
```
38
39
### InjectionPoint
40
41
Base interface for points where dependency injection occurs.
42
43
```java { .api }
44
public interface InjectionPoint<T> {
45
BeanDefinition getDeclaringBean();
46
Argument<T> getArgument();
47
AnnotationMetadata getAnnotationMetadata();
48
}
49
```
50
51
### MethodInjectionPoint
52
53
Injection point for method injection (setter injection, @PostConstruct methods).
54
55
```java { .api }
56
public interface MethodInjectionPoint<B, T> extends InjectionPoint<T>, ExecutableMethod<B, T> {
57
T invoke(B instance, BeanResolutionContext resolutionContext, BeanContext context);
58
T invoke(B instance, BeanResolutionContext resolutionContext, BeanContext context, Object... args);
59
boolean requiresReflection();
60
}
61
```
62
63
### FieldInjectionPoint
64
65
Injection point for field injection.
66
67
```java { .api }
68
public interface FieldInjectionPoint<B, T> extends InjectionPoint<T> {
69
void set(B instance, BeanResolutionContext resolutionContext, BeanContext context);
70
T get(B instance);
71
String getName();
72
boolean requiresReflection();
73
}
74
```
75
76
## Bean Resolution Context
77
78
### BeanResolutionContext
79
80
Context information during bean resolution and creation.
81
82
```java { .api }
83
public interface BeanResolutionContext extends AutoCloseable {
84
BeanContext getContext();
85
BeanDefinition<?> getRootDefinition();
86
Path getPath();
87
<T> Optional<T> get(CharSequence name, Class<T> requiredType);
88
BeanResolutionContext copy();
89
void close();
90
}
91
```
92
93
### Path
94
95
Represents the resolution path during bean creation.
96
97
```java { .api }
98
public interface Path {
99
Optional<Path> getParent();
100
String toString();
101
Path.Segment getCurrentSegment();
102
103
interface Segment {
104
String getName();
105
BeanDefinition getDeclaringType();
106
Argument getArgument();
107
}
108
}
109
```
110
111
## Argument Metadata
112
113
### Argument
114
115
Represents method/constructor arguments with type information.
116
117
```java { .api }
118
public class Argument<T> implements AnnotatedElement {
119
public static <T> Argument<T> of(Class<T> type);
120
public static <T> Argument<T> of(Class<T> type, String name);
121
public static <T> Argument<T> of(Class<T> type, AnnotationMetadata annotationMetadata);
122
123
public Class<T> getType();
124
public String getName();
125
public Argument[] getTypeParameters();
126
public Map<String, Argument<?>> getTypeVariables();
127
public boolean isNullable();
128
public boolean isOptional();
129
}
130
```
131
132
## Usage Examples
133
134
### Basic Bean Definition Usage
135
136
```java
137
import io.micronaut.context.ApplicationContext;
138
import io.micronaut.inject.BeanDefinition;
139
140
public class BeanDefinitionExample {
141
public static void main(String[] args) {
142
try (ApplicationContext context = ApplicationContext.run()) {
143
// Get bean definition
144
BeanDefinition<UserService> definition =
145
context.getBeanDefinition(UserService.class);
146
147
// Examine bean metadata
148
System.out.println("Bean type: " + definition.getBeanType());
149
System.out.println("Is singleton: " + definition.isSingleton());
150
System.out.println("Constructor args: " + definition.getConstructorArguments());
151
152
// Create instance using definition
153
UserService service = definition.instantiate(
154
context.getBeanResolutionContext(),
155
context
156
);
157
}
158
}
159
}
160
```
161
162
### Inspecting Injection Points
163
164
```java
165
import io.micronaut.context.ApplicationContext;
166
import io.micronaut.inject.BeanDefinition;
167
import io.micronaut.inject.MethodInjectionPoint;
168
import io.micronaut.inject.FieldInjectionPoint;
169
170
public class InjectionPointExample {
171
public static void main(String[] args) {
172
try (ApplicationContext context = ApplicationContext.run()) {
173
BeanDefinition<OrderService> definition =
174
context.getBeanDefinition(OrderService.class);
175
176
// Inspect method injection points
177
Collection<MethodInjectionPoint<OrderService, ?>> methodInjections =
178
definition.getInjectedMethods();
179
180
for (MethodInjectionPoint<OrderService, ?> injection : methodInjections) {
181
System.out.println("Method: " + injection.getName());
182
System.out.println("Argument: " + injection.getArgument());
183
}
184
185
// Inspect field injection points
186
Collection<FieldInjectionPoint<OrderService, ?>> fieldInjections =
187
definition.getInjectedFields();
188
189
for (FieldInjectionPoint<OrderService, ?> injection : fieldInjections) {
190
System.out.println("Field: " + injection.getName());
191
System.out.println("Type: " + injection.getArgument().getType());
192
}
193
}
194
}
195
}
196
```
197
198
### Manual Bean Creation with Arguments
199
200
```java
201
import io.micronaut.context.ApplicationContext;
202
import io.micronaut.inject.BeanDefinition;
203
204
public class ManualCreationExample {
205
public static void main(String[] args) {
206
try (ApplicationContext context = ApplicationContext.run()) {
207
BeanDefinition<DatabaseService> definition =
208
context.getBeanDefinition(DatabaseService.class);
209
210
// Create with custom arguments
211
DatabaseService service = definition.instantiate(
212
context.getBeanResolutionContext(),
213
context,
214
"jdbc:postgresql://localhost/mydb", // connection string
215
"myuser", // username
216
"mypass" // password
217
);
218
219
service.connect();
220
}
221
}
222
}
223
```
224
225
### Examining Method Arguments
226
227
```java
228
import io.micronaut.context.ApplicationContext;
229
import io.micronaut.inject.BeanDefinition;
230
import io.micronaut.context.Argument;
231
232
public class ArgumentExample {
233
public static void main(String[] args) {
234
try (ApplicationContext context = ApplicationContext.run()) {
235
BeanDefinition<PaymentService> definition =
236
context.getBeanDefinition(PaymentService.class);
237
238
// Examine constructor arguments
239
List<Argument<?>> constructorArgs = definition.getConstructorArguments();
240
241
for (Argument<?> arg : constructorArgs) {
242
System.out.println("Argument name: " + arg.getName());
243
System.out.println("Argument type: " + arg.getType());
244
System.out.println("Is nullable: " + arg.isNullable());
245
System.out.println("Is optional: " + arg.isOptional());
246
247
// Check for generic type parameters
248
Argument<?>[] typeParams = arg.getTypeParameters();
249
if (typeParams.length > 0) {
250
System.out.println("Generic parameters: " + Arrays.toString(typeParams));
251
}
252
}
253
}
254
}
255
}
256
```
257
258
## Bean Factory Implementation
259
260
### Custom Bean Factory
261
262
```java
263
import io.micronaut.inject.BeanFactory;
264
import io.micronaut.inject.BeanDefinition;
265
import io.micronaut.context.BeanResolutionContext;
266
import io.micronaut.context.BeanContext;
267
import jakarta.inject.Singleton;
268
269
@Singleton
270
public class CustomServiceFactory implements BeanFactory<CustomService> {
271
272
@Override
273
public CustomService build(BeanResolutionContext resolutionContext,
274
BeanContext context,
275
BeanDefinition<CustomService> definition) {
276
277
// Custom bean creation logic
278
String environment = context.getEnvironment().getActiveNames().iterator().next();
279
280
if ("prod".equals(environment)) {
281
return new ProductionCustomService();
282
} else {
283
return new DevelopmentCustomService();
284
}
285
}
286
}
287
```
288
289
## Resolution Context Usage
290
291
### Working with Resolution Context
292
293
```java
294
import io.micronaut.context.ApplicationContext;
295
import io.micronaut.context.BeanResolutionContext;
296
import io.micronaut.inject.BeanDefinition;
297
298
public class ResolutionContextExample {
299
public static void main(String[] args) {
300
try (ApplicationContext context = ApplicationContext.run()) {
301
302
try (BeanResolutionContext resolutionContext = context.getBeanResolutionContext()) {
303
BeanDefinition<ComplexService> definition =
304
context.getBeanDefinition(ComplexService.class);
305
306
// Create bean with resolution context
307
ComplexService service = definition.instantiate(resolutionContext, context);
308
309
// Resolution context tracks the path
310
System.out.println("Resolution path: " + resolutionContext.getPath());
311
312
service.performComplexOperation();
313
}
314
}
315
}
316
}
317
```
318
319
## Implementation Classes
320
321
### Abstract Bean Definition
322
323
Base implementation class for bean definitions.
324
325
```java { .api }
326
public abstract class AbstractBeanDefinition<T> implements BeanDefinition<T> {
327
protected AbstractBeanDefinition(Class<T> type,
328
MethodOrFieldReference constructor,
329
AnnotationMetadata annotationMetadata,
330
MethodReference[] methodInjection,
331
FieldReference[] fieldInjection,
332
ExecutableMethodsDefinition<T> executableMethodsDefinition,
333
Map<String, Argument<?>[]> typeArgumentsMap);
334
335
// Implements BeanDefinition interface methods
336
}
337
```
338
339
### Default Field Injection Point
340
341
Default implementation for field injection.
342
343
```java { .api }
344
public class DefaultFieldInjectionPoint<B, T> implements FieldInjectionPoint<B, T> {
345
public DefaultFieldInjectionPoint(BeanDefinition declaringBean,
346
Class<T> fieldType,
347
String field,
348
AnnotationMetadata annotationMetadata,
349
Argument[] arguments);
350
351
// Implements FieldInjectionPoint interface methods
352
}
353
```
354
355
## Type Information
356
357
### Argument Creation
358
359
```java
360
import io.micronaut.context.Argument;
361
362
public class ArgumentCreationExample {
363
public static void main(String[] args) {
364
// Create basic argument
365
Argument<String> stringArg = Argument.of(String.class, "message");
366
367
// Create generic argument
368
Argument<List<String>> listArg = Argument.of(List.class, "items")
369
.withTypeParameters(Argument.of(String.class));
370
371
// Create optional argument
372
Argument<Optional<Integer>> optionalArg = Argument.of(Optional.class, "count")
373
.withTypeParameters(Argument.of(Integer.class));
374
375
System.out.println("String arg: " + stringArg);
376
System.out.println("List arg: " + listArg);
377
System.out.println("Optional arg: " + optionalArg);
378
}
379
}
380
```