0
# Bean Location and Providers
1
2
Bean providers and locators offer flexible, programmatic access to beans in the Micronaut context. They enable lazy instantiation, optional dependencies, and type-safe collection access to beans.
3
4
## Core Interfaces
5
6
### BeanProvider
7
8
Enhanced provider interface that extends Jakarta Provider with additional capabilities for bean introspection and collection access.
9
10
```java { .api }
11
/**
12
* Enhanced provider interface for accessing beans with additional capabilities
13
* @param <T> The bean type
14
*/
15
public interface BeanProvider<T> extends jakarta.inject.Provider<T> {
16
/**
17
* Check if at least one bean of this type is available
18
* @return true if a bean is present
19
*/
20
boolean isPresent();
21
22
/**
23
* Check if exactly one bean of this type is available
24
* @return true if only one bean matches
25
*/
26
boolean isUnique();
27
28
/**
29
* Get an iterator over all available beans of this type
30
* @return Iterator of bean instances
31
*/
32
Iterator<T> iterator();
33
34
/**
35
* Get a stream of all available beans of this type
36
* @return Stream of bean instances
37
*/
38
Stream<T> stream();
39
40
/**
41
* Get the first available bean instance
42
* @return Bean instance
43
* @throws NoSuchBeanException if no bean is available
44
*/
45
@Override
46
T get();
47
}
48
```
49
50
**Usage Examples:**
51
52
```java
53
import io.micronaut.context.BeanProvider;
54
import jakarta.inject.Inject;
55
import jakarta.inject.Singleton;
56
57
@Singleton
58
public class NotificationService {
59
60
// Lazy provider - bean resolved on first access
61
private final BeanProvider<EmailService> emailProvider;
62
63
@Inject
64
public NotificationService(BeanProvider<EmailService> emailProvider) {
65
this.emailProvider = emailProvider;
66
}
67
68
public void sendNotification(String message) {
69
// Check if email service is available before using it
70
if (emailProvider.isPresent()) {
71
EmailService emailService = emailProvider.get();
72
emailService.send(message);
73
}
74
75
// Process all notification handlers
76
emailProvider.stream().forEach(handler -> handler.send(message));
77
}
78
}
79
80
// Multiple implementations scenario
81
@Singleton
82
public class AggregatorService {
83
84
private final BeanProvider<DataProcessor> processors;
85
86
@Inject
87
public AggregatorService(BeanProvider<DataProcessor> processors) {
88
this.processors = processors;
89
}
90
91
public void processData(Data data) {
92
// Use all available processors
93
processors.iterator().forEachRemaining(processor ->
94
processor.process(data)
95
);
96
}
97
}
98
```
99
100
### BeanLocator
101
102
Core interface for locating beans in the context with various resolution strategies.
103
104
```java { .api }
105
/**
106
* Core interface for bean location and resolution
107
*/
108
public interface BeanLocator {
109
/**
110
* Get a required bean of the given type
111
* @param beanType The bean type
112
* @return Bean instance
113
* @throws NoSuchBeanException if bean not found
114
*/
115
<T> T getBean(Class<T> beanType);
116
117
/**
118
* Get a required bean with qualifier
119
* @param beanType The bean type
120
* @param qualifier The qualifier
121
* @return Bean instance
122
* @throws NoSuchBeanException if bean not found
123
*/
124
<T> T getBean(Class<T> beanType, Qualifier<T> qualifier);
125
126
/**
127
* Find an optional bean of the given type
128
* @param beanType The bean type
129
* @return Optional bean instance
130
*/
131
<T> Optional<T> findBean(Class<T> beanType);
132
133
/**
134
* Find an optional bean with qualifier
135
* @param beanType The bean type
136
* @param qualifier The qualifier
137
* @return Optional bean instance
138
*/
139
<T> Optional<T> findBean(Class<T> beanType, Qualifier<T> qualifier);
140
141
/**
142
* Get all beans of the given type
143
* @param beanType The bean type
144
* @return Collection of bean instances
145
*/
146
<T> Collection<T> getBeansOfType(Class<T> beanType);
147
148
/**
149
* Get all beans of the given type with qualifier
150
* @param beanType The bean type
151
* @param qualifier The qualifier
152
* @return Collection of bean instances
153
*/
154
<T> Collection<T> getBeansOfType(Class<T> beanType, Qualifier<T> qualifier);
155
156
/**
157
* Get bean provider for the given type
158
* @param beanType The bean type
159
* @return BeanProvider instance
160
*/
161
<T> BeanProvider<T> getBeanProvider(Class<T> beanType);
162
163
/**
164
* Get bean provider for the given type with qualifier
165
* @param beanType The bean type
166
* @param qualifier The qualifier
167
* @return BeanProvider instance
168
*/
169
<T> BeanProvider<T> getBeanProvider(Class<T> beanType, Qualifier<T> qualifier);
170
}
171
```
172
173
### BeanDefinitionRegistry
174
175
Registry interface providing metadata and introspection capabilities for bean definitions.
176
177
```java { .api }
178
/**
179
* Registry for bean definition metadata and introspection
180
*/
181
public interface BeanDefinitionRegistry {
182
/**
183
* Check if a bean of the given type exists
184
* @param beanType The bean type
185
* @return true if bean exists
186
*/
187
<T> boolean containsBean(Class<T> beanType);
188
189
/**
190
* Check if a bean exists with qualifier
191
* @param beanType The bean type
192
* @param qualifier The qualifier
193
* @return true if bean exists
194
*/
195
<T> boolean containsBean(Class<T> beanType, Qualifier<T> qualifier);
196
197
/**
198
* Find bean definition for the given type
199
* @param beanType The bean type
200
* @return Optional bean definition
201
*/
202
<T> Optional<BeanDefinition<T>> findBeanDefinition(Class<T> beanType);
203
204
/**
205
* Find bean definition with qualifier
206
* @param beanType The bean type
207
* @param qualifier The qualifier
208
* @return Optional bean definition
209
*/
210
<T> Optional<BeanDefinition<T>> findBeanDefinition(Class<T> beanType, Qualifier<T> qualifier);
211
212
/**
213
* Get all bean definitions for the given type
214
* @param beanType The bean type
215
* @return Collection of bean definitions
216
*/
217
<T> Collection<BeanDefinition<T>> getBeanDefinitions(Class<T> beanType);
218
219
/**
220
* Get single bean definition for the given type
221
* @param beanType The bean type
222
* @return Bean definition
223
* @throws NoSuchBeanException if not found
224
* @throws NonUniqueBeanException if multiple found
225
*/
226
<T> BeanDefinition<T> getBeanDefinition(Class<T> beanType);
227
}
228
```
229
230
## Provider Injection Patterns
231
232
### Optional Dependencies
233
234
```java
235
@Singleton
236
public class OptionalFeatureService {
237
238
private final BeanProvider<CacheService> cacheProvider;
239
private final BeanProvider<MetricsService> metricsProvider;
240
241
@Inject
242
public OptionalFeatureService(
243
BeanProvider<CacheService> cacheProvider,
244
BeanProvider<MetricsService> metricsProvider
245
) {
246
this.cacheProvider = cacheProvider;
247
this.metricsProvider = metricsProvider;
248
}
249
250
public String processRequest(String request) {
251
String result = performCoreLogic(request);
252
253
// Optional caching
254
if (cacheProvider.isPresent()) {
255
cacheProvider.get().cache(request, result);
256
}
257
258
// Optional metrics
259
if (metricsProvider.isPresent()) {
260
metricsProvider.get().recordRequest();
261
}
262
263
return result;
264
}
265
}
266
```
267
268
### Collection-based Processing
269
270
```java
271
@Singleton
272
public class PluginManager {
273
274
private final BeanProvider<Plugin> plugins;
275
276
@Inject
277
public PluginManager(BeanProvider<Plugin> plugins) {
278
this.plugins = plugins;
279
}
280
281
public void initializePlugins() {
282
plugins.stream()
283
.sorted(Comparator.comparing(Plugin::getPriority))
284
.forEach(Plugin::initialize);
285
}
286
287
public void processWithPlugins(Event event) {
288
plugins.iterator().forEachRemaining(plugin ->
289
plugin.process(event)
290
);
291
}
292
}
293
```
294
295
### Lazy Initialization
296
297
```java
298
@Singleton
299
public class ExpensiveResourceManager {
300
301
private final BeanProvider<DatabaseConnection> dbProvider;
302
private final BeanProvider<FileSystem> fsProvider;
303
304
@Inject
305
public ExpensiveResourceManager(
306
BeanProvider<DatabaseConnection> dbProvider,
307
BeanProvider<FileSystem> fsProvider
308
) {
309
this.dbProvider = dbProvider;
310
this.fsProvider = fsProvider;
311
}
312
313
public void performDatabaseOperation() {
314
// Database connection only created when needed
315
DatabaseConnection db = dbProvider.get();
316
db.execute("SELECT * FROM users");
317
}
318
319
public void performFileOperation() {
320
// File system only initialized when needed
321
FileSystem fs = fsProvider.get();
322
fs.readFile("config.properties");
323
}
324
}
325
```
326
327
## Types
328
329
### Provider-related Types
330
331
```java { .api }
332
public interface Qualifier<T> {
333
<BT extends BeanType<T>> Stream<BT> reduce(Class<T> beanType, Stream<BT> candidates);
334
boolean equals(Object o);
335
int hashCode();
336
}
337
338
public interface BeanResolutionContext {
339
BeanContext getContext();
340
BeanDefinition<?> getRootDefinition();
341
Path getPath();
342
BeanResolutionContext copy();
343
}
344
345
public interface BeanCreationContext<T> extends BeanResolutionContext {
346
BeanDefinition<T> definition();
347
CreatedBean<T> create() throws BeanCreationException;
348
}
349
```