Spring annotation processor for generating component metadata indexes to optimize application startup performance
npx @tessl/cli install tessl/maven-org-springframework--spring-context-indexer@6.2.00
# Spring Context Indexer
1
2
Spring Context Indexer is a Java annotation processor that generates component metadata indexes during compilation to optimize Spring application startup performance. It scans classes annotated with Spring stereotypes and creates an index file that Spring uses to avoid runtime classpath scanning.
3
4
**Note: This component is deprecated as of Spring Framework 6.1 in favor of the AOT (Ahead of Time) engine.**
5
6
## Package Information
7
8
- **Package Name**: org.springframework:spring-context-indexer
9
- **Package Type**: Maven
10
- **Language**: Java
11
- **Installation**: Add dependency to `pom.xml`:
12
13
```xml
14
<dependency>
15
<groupId>org.springframework</groupId>
16
<artifactId>spring-context-indexer</artifactId>
17
<version>6.2.10</version>
18
<optional>true</optional>
19
</dependency>
20
```
21
22
For Gradle:
23
```gradle
24
dependencies {
25
compileOnly 'org.springframework:spring-context-indexer:6.2.10'
26
}
27
```
28
29
## Core Imports
30
31
```java
32
import org.springframework.context.index.processor.CandidateComponentsIndexer;
33
```
34
35
## Basic Usage
36
37
The annotation processor works automatically during compilation when the dependency is present. No explicit instantiation is needed:
38
39
```java
40
// Classes with Spring stereotypes are automatically indexed
41
@Component
42
public class MyService {
43
// Implementation
44
}
45
46
@Repository
47
public class MyRepository {
48
// Implementation
49
}
50
```
51
52
The processor generates `META-INF/spring.components` containing:
53
```properties
54
com.example.MyService=org.springframework.stereotype.Component
55
com.example.MyRepository=org.springframework.stereotype.Repository
56
```
57
58
## Architecture
59
60
The Spring Context Indexer follows the standard Java annotation processing architecture:
61
62
- **Annotation Processor**: `CandidateComponentsIndexer` implements `javax.annotation.processing.Processor`
63
- **Stereotype Detection**: Multiple providers detect different types of component annotations
64
- **Metadata Collection**: Collects and merges component metadata across compilation rounds
65
- **File Generation**: Writes component index to `META-INF/spring.components` in properties format
66
67
## Capabilities
68
69
### Annotation Processing
70
71
The main annotation processor that generates component metadata indexes.
72
73
```java { .api }
74
@Deprecated(since = "6.1", forRemoval = true)
75
public class CandidateComponentsIndexer implements Processor {
76
77
/**
78
* Returns the set of supported processor options (empty set)
79
*/
80
public Set<String> getSupportedOptions();
81
82
/**
83
* Returns the set of annotation types supported by this processor
84
* @return Set containing "*" (all annotations)
85
*/
86
public Set<String> getSupportedAnnotationTypes();
87
88
/**
89
* Returns the latest supported source version
90
*/
91
public SourceVersion getSupportedSourceVersion();
92
93
/**
94
* Initializes the processor with the processing environment
95
* @param env The processing environment
96
*/
97
public synchronized void init(ProcessingEnvironment env);
98
99
/**
100
* Processes the annotations for the current round
101
* @param annotations The annotation types requested to be processed
102
* @param roundEnv Environment for information about the current round
103
* @return false (does not claim the annotations)
104
*/
105
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv);
106
107
/**
108
* Returns completions for annotation values (returns empty list)
109
* @param element The element being annotated
110
* @param annotation The partial annotation being applied
111
* @param member The annotation member to complete
112
* @param userText The user's partial input
113
* @return Empty list
114
*/
115
public Iterable<? extends Completion> getCompletions(
116
Element element, AnnotationMirror annotation,
117
ExecutableElement member, String userText);
118
}
119
```
120
121
### Component Metadata Model
122
123
Data structures representing component metadata collected during processing.
124
125
```java { .api }
126
/**
127
* Container for candidate component metadata items
128
*/
129
class CandidateComponentsMetadata {
130
131
/**
132
* Default constructor creating empty metadata container
133
*/
134
public CandidateComponentsMetadata();
135
136
/**
137
* Adds a metadata item to the collection
138
* @param item The metadata item to add
139
*/
140
public void add(ItemMetadata item);
141
142
/**
143
* Returns an unmodifiable list of all metadata items
144
* @return List of metadata items
145
*/
146
public List<ItemMetadata> getItems();
147
148
/**
149
* String representation of the metadata
150
*/
151
public String toString();
152
}
153
154
/**
155
* Represents a single component entry with type and stereotypes
156
*/
157
class ItemMetadata {
158
159
/**
160
* Creates metadata for a component type with its stereotypes
161
* @param type The fully qualified class name
162
* @param stereotypes Set of stereotype markers (annotations)
163
*/
164
public ItemMetadata(String type, Set<String> stereotypes);
165
166
/**
167
* Returns the component type (fully qualified class name)
168
* @return The component type
169
*/
170
public String getType();
171
172
/**
173
* Returns the set of stereotypes for this component
174
* @return Set of stereotype markers
175
*/
176
public Set<String> getStereotypes();
177
}
178
```
179
180
### Metadata Collection
181
182
Collects and manages component metadata during annotation processing rounds.
183
184
```java { .api }
185
/**
186
* Collects metadata during annotation processing rounds
187
*/
188
class MetadataCollector {
189
190
/**
191
* Creates a metadata collector
192
* @param processingEnvironment The processing environment
193
* @param previousMetadata Previously collected metadata or null
194
*/
195
public MetadataCollector(ProcessingEnvironment processingEnvironment,
196
CandidateComponentsMetadata previousMetadata);
197
198
/**
199
* Marks elements as processed for the current round
200
* @param roundEnv The round environment containing elements to process
201
*/
202
public void processing(RoundEnvironment roundEnv);
203
204
/**
205
* Adds a metadata item to the collection
206
* @param metadata The metadata item to add
207
*/
208
public void add(ItemMetadata metadata);
209
210
/**
211
* Returns the collected metadata, merged with previous rounds
212
* @return Complete component metadata
213
*/
214
public CandidateComponentsMetadata getMetadata();
215
}
216
```
217
218
### Metadata Storage
219
220
Handles reading and writing component metadata to the filesystem.
221
222
```java { .api }
223
/**
224
* Stores component metadata in META-INF/spring.components
225
*/
226
class MetadataStore {
227
228
/** The path where component metadata is stored */
229
static final String METADATA_PATH = "META-INF/spring.components";
230
231
/**
232
* Creates a metadata store for the given processing environment
233
* @param environment The annotation processing environment
234
*/
235
public MetadataStore(ProcessingEnvironment environment);
236
237
/**
238
* Reads existing metadata from the filesystem
239
* @return Previously stored metadata or null if not found
240
*/
241
public CandidateComponentsMetadata readMetadata();
242
243
/**
244
* Writes component metadata to META-INF/spring.components
245
* @param metadata The metadata to write
246
* @throws IOException If writing fails
247
*/
248
public void writeMetadata(CandidateComponentsMetadata metadata) throws IOException;
249
}
250
```
251
252
### Stereotype Detection
253
254
Interfaces and implementations for detecting component stereotypes.
255
256
```java { .api }
257
/**
258
* Interface for providing stereotypes that match an element
259
*/
260
interface StereotypesProvider {
261
262
/**
263
* Returns the stereotypes present on the given element
264
* @param element The element to examine
265
* @return Set of stereotype names or empty set if none found
266
*/
267
Set<String> getStereotypes(Element element);
268
}
269
270
/**
271
* Detects stereotypes marked with @Indexed annotation
272
*/
273
class IndexedStereotypesProvider implements StereotypesProvider {
274
275
/** The annotation that marks indexed stereotypes */
276
private static final String INDEXED_ANNOTATION = "org.springframework.stereotype.Indexed";
277
278
/**
279
* Creates provider with the given type helper
280
* @param typeHelper Utility for type operations
281
*/
282
public IndexedStereotypesProvider(TypeHelper typeHelper);
283
284
/**
285
* Returns stereotypes marked with @Indexed on the element or its annotations
286
* @param element The element to examine
287
* @return Set of indexed stereotypes
288
*/
289
public Set<String> getStereotypes(Element element);
290
}
291
292
/**
293
* Detects standard Jakarta/Java EE and legacy javax annotations
294
*/
295
class StandardStereotypesProvider implements StereotypesProvider {
296
297
/**
298
* Creates provider with the given type helper (package-private constructor)
299
* @param typeHelper Utility for type operations
300
*/
301
StandardStereotypesProvider(TypeHelper typeHelper);
302
303
/**
304
* Returns jakarta.* and javax.* annotations as stereotypes
305
* @param element The element to examine (must be class or interface)
306
* @return Set of standard stereotypes
307
*/
308
public Set<String> getStereotypes(Element element);
309
}
310
311
/**
312
* Provides package-info stereotype for package elements
313
*/
314
class PackageInfoStereotypesProvider implements StereotypesProvider {
315
316
/** The stereotype name for package elements */
317
public static final String STEREOTYPE = "package-info";
318
319
/**
320
* Returns package-info stereotype for package elements
321
* @param element The element to examine
322
* @return Set containing "package-info" for packages, empty otherwise
323
*/
324
public Set<String> getStereotypes(Element element);
325
}
326
```
327
328
### Type Utilities
329
330
Utility class for working with Java type system during annotation processing.
331
332
```java { .api }
333
/**
334
* Utilities for working with types during annotation processing
335
*/
336
class TypeHelper {
337
338
/**
339
* Creates type helper for the given processing environment
340
* @param env The processing environment
341
*/
342
public TypeHelper(ProcessingEnvironment env);
343
344
/**
345
* Gets the fully qualified type name from an element
346
* @param element The element to get type for
347
* @return Fully qualified type name or null
348
*/
349
public String getType(Element element);
350
351
/**
352
* Gets the fully qualified type name from an annotation mirror
353
* @param annotation The annotation to get type for
354
* @return Fully qualified annotation type name or null
355
*/
356
public String getType(AnnotationMirror annotation);
357
358
/**
359
* Gets the fully qualified type name from a type mirror
360
* @param type The type mirror to convert
361
* @return Fully qualified type name or toString() result
362
*/
363
public String getType(TypeMirror type);
364
365
/**
366
* Returns the superclass element of the given element
367
* @param element The element to get superclass for
368
* @return Superclass element or null if element represents Object
369
*/
370
public Element getSuperClass(Element element);
371
372
/**
373
* Returns interfaces directly implemented by the element
374
* @param element The element to get interfaces for
375
* @return List of directly implemented interfaces
376
*/
377
public List<Element> getDirectInterfaces(Element element);
378
379
/**
380
* Returns all annotation mirrors for an element, handling exceptions
381
* @param e The element to get annotations for
382
* @return List of annotation mirrors or empty list if error occurs
383
*/
384
public List<? extends AnnotationMirror> getAllAnnotationMirrors(Element e);
385
}
386
```
387
388
### Properties Marshalling
389
390
Utilities for serializing metadata to and from properties format.
391
392
```java { .api }
393
/**
394
* Marshals component metadata as properties files
395
*/
396
abstract class PropertiesMarshaller {
397
398
/**
399
* Writes component metadata to an output stream in properties format
400
* @param metadata The metadata to write
401
* @param out The output stream to write to
402
* @throws IOException If writing fails
403
*/
404
public static void write(CandidateComponentsMetadata metadata, OutputStream out)
405
throws IOException;
406
407
/**
408
* Reads component metadata from an input stream in properties format
409
* @param in The input stream to read from
410
* @return Parsed component metadata
411
* @throws IOException If reading fails
412
*/
413
public static CandidateComponentsMetadata read(InputStream in)
414
throws IOException;
415
}
416
417
/**
418
* Properties implementation that maintains sorted key order
419
*/
420
class SortedProperties extends Properties {
421
422
/** System line separator */
423
static final String EOL = System.lineSeparator();
424
425
/**
426
* Creates sorted properties with comment control
427
* @param omitComments true to omit comments when storing
428
*/
429
SortedProperties(boolean omitComments);
430
431
/**
432
* Creates sorted properties from existing properties
433
* @param properties Source properties to copy from
434
* @param omitComments true to omit comments when storing
435
*/
436
SortedProperties(Properties properties, boolean omitComments);
437
438
// Overridden methods maintain sorted order:
439
// store(), storeToXML(), keys(), keySet(), entrySet()
440
}
441
```
442
443
## Error Handling
444
445
The annotation processor handles errors gracefully:
446
447
- **Missing annotations**: Silently ignores elements without stereotype annotations
448
- **Invalid types**: Uses fallback toString() for unrecognized type mirrors
449
- **I/O failures**: Throws IllegalStateException for metadata write failures
450
- **Processing errors**: Returns empty lists/sets rather than failing compilation
451
452
Common exceptions:
453
- `IllegalStateException`: Thrown when metadata cannot be written to filesystem
454
- `IOException`: Thrown during file I/O operations in MetadataStore
455
456
## Configuration
457
458
The processor is configured automatically through the Java annotation processing framework:
459
460
1. **Service registration**: Listed in `META-INF/services/javax.annotation.processing.Processor`
461
2. **Classpath detection**: Automatically discovered when jar is on annotation processor path
462
3. **No options**: The processor accepts no configuration options (returns empty set from `getSupportedOptions()`)
463
464
## Generated Output
465
466
The processor generates a single file at compile time:
467
468
**File**: `META-INF/spring.components`
469
**Format**: Java properties file
470
**Content**: Component type to stereotype mappings
471
472
Example output:
473
```properties
474
com.example.service.UserService=org.springframework.stereotype.Service
475
com.example.repository.UserRepository=org.springframework.stereotype.Repository
476
com.example.controller.UserController=org.springframework.stereotype.Controller
477
com.example.config.AppConfig=org.springframework.stereotype.Component
478
```
479
480
This index is consumed by Spring's `ApplicationContext` to optimize component scanning at runtime.