0
# AOT and Native Compilation
1
2
Ahead-of-time compilation support for native image generation, providing build-time optimization and reflection-free bean instantiation. This system enables Spring applications to be compiled to native images with GraalVM, significantly reducing startup time and memory footprint.
3
4
## Capabilities
5
6
### Bean Registration AOT Processing
7
8
Infrastructure for processing bean definitions at build time to generate optimized instantiation code.
9
10
```java { .api }
11
/**
12
* AOT processor that contributes to bean registration code generation.
13
*/
14
interface BeanRegistrationAotProcessor {
15
/**
16
* Process the given RegisteredBean instance ahead of time and return a contribution or null.
17
* @param registeredBean the registered bean to process
18
* @return a BeanRegistrationAotContribution instance or null
19
*/
20
BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean);
21
}
22
23
/**
24
* AOT contribution from a BeanRegistrationAotProcessor, used to register a single bean definition.
25
*/
26
interface BeanRegistrationAotContribution {
27
/**
28
* Apply this contribution to the given BeanRegistrationCode.
29
* @param generationContext the generation context
30
* @param beanRegistrationCode the bean registration code
31
*/
32
void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode);
33
}
34
35
/**
36
* Interface that defines the contract for code that registers a single bean.
37
*/
38
interface BeanRegistrationCode {
39
/**
40
* Return the class name of the bean registration.
41
* @return the class name
42
*/
43
ClassName getClassName();
44
45
/**
46
* Return the methods that contain the bean registration code.
47
* @return the registration methods
48
*/
49
MethodReference[] getMethods();
50
51
/**
52
* Return the instance supplier code generator.
53
* @return the instance supplier code generator
54
*/
55
CodeGenerator getInstanceSupplierCodeGenerator();
56
}
57
58
/**
59
* Interface that defines the contract for code that registers all beans.
60
*/
61
interface BeanRegistrationsCode {
62
/**
63
* Return the class name that contains the bean registrations.
64
* @return the class name
65
*/
66
ClassName getClassName();
67
68
/**
69
* Return the method that contains the bean registration code.
70
* @return the registration method
71
*/
72
MethodReference getInitializerMethod();
73
}
74
```
75
76
### Bean Factory Initialization AOT Processing
77
78
Support for processing bean factory initialization logic at build time.
79
80
```java { .api }
81
/**
82
* AOT processor that contributes to bean factory initialization code generation.
83
*/
84
interface BeanFactoryInitializationAotProcessor {
85
/**
86
* Process the given ConfigurableListableBeanFactory instance ahead of time and return a contribution or null.
87
* @param beanFactory the bean factory to process
88
* @return a BeanFactoryInitializationAotContribution instance or null
89
*/
90
BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory);
91
}
92
93
/**
94
* AOT contribution from a BeanFactoryInitializationAotProcessor, used to initialize a bean factory.
95
*/
96
interface BeanFactoryInitializationAotContribution {
97
/**
98
* Apply this contribution to the given BeanFactoryInitializationCode.
99
* @param generationContext the generation context
100
* @param beanFactoryInitializationCode the bean factory initialization code
101
*/
102
void applyTo(GenerationContext generationContext, BeanFactoryInitializationCode beanFactoryInitializationCode);
103
}
104
105
/**
106
* Interface that defines the contract for code that initializes a bean factory.
107
*/
108
interface BeanFactoryInitializationCode {
109
/**
110
* Return the type of the bean factory.
111
* @return the bean factory type
112
*/
113
TypeSpec.Builder getTypeBuilder();
114
115
/**
116
* Return the methods that contain the bean factory initialization code.
117
* @return the initialization methods
118
*/
119
MethodSpec.Builder[] getMethods();
120
}
121
```
122
123
### Instance Supplier Code Generation
124
125
Code generation for creating optimized instance suppliers that avoid reflection.
126
127
```java { .api }
128
/**
129
* Code generator for instance supplier lambda expressions.
130
*/
131
class InstanceSupplierCodeGenerator {
132
/**
133
* Create a new InstanceSupplierCodeGenerator instance.
134
* @param generationContext the generation context to use
135
* @param className the class name being generated
136
* @param methods the methods that are available
137
* @param allowDirectSupplierShortcut whether to allow direct supplier shortcuts
138
*/
139
public InstanceSupplierCodeGenerator(GenerationContext generationContext, ClassName className,
140
MultiStatement methods, boolean allowDirectSupplierShortcut);
141
142
/**
143
* Generate the instance supplier code for the given registered bean and executable.
144
* @param registeredBean the registered bean
145
* @param constructorOrFactoryMethod the constructor or factory method
146
* @return the generated code block
147
*/
148
public CodeBlock generateCode(RegisteredBean registeredBean, Executable constructorOrFactoryMethod);
149
150
/**
151
* Generate the instance supplier code for the given registered bean and instantiation descriptor.
152
* @param registeredBean the registered bean
153
* @param instantiationDescriptor the instantiation descriptor
154
* @return the generated code block
155
*/
156
public CodeBlock generateCode(RegisteredBean registeredBean, InstantiationDescriptor instantiationDescriptor);
157
158
/**
159
* Generate the instance supplier code for the given registered bean and instance supplier.
160
* @param registeredBean the registered bean
161
* @param instanceSupplier the instance supplier
162
* @return the generated code block
163
*/
164
public CodeBlock generateCode(RegisteredBean registeredBean, InstanceSupplier<?> instanceSupplier);
165
166
/**
167
* Check whether the given bean class has a constructor with an optional parameter.
168
* @param beanClass the bean class to check
169
* @return true if the bean class has a constructor with an optional parameter
170
*/
171
public static boolean hasConstructorWithOptionalParameter(Class<?> beanClass);
172
173
/**
174
* Register reflection hints for the given executable.
175
* @param runtimeHints the runtime hints
176
* @param executable the executable to register hints for
177
*/
178
public void registerRuntimeHints(RuntimeHints runtimeHints, Executable executable);
179
}
180
```
181
182
### Autowired Arguments Code Generation
183
184
Support for generating code that resolves autowired constructor and method arguments.
185
186
```java { .api }
187
/**
188
* Interface for resolving autowired arguments in generated code.
189
*/
190
interface AutowiredArguments {
191
/**
192
* Resolve the arguments for the given parameter types.
193
* @param parameterTypes the parameter types
194
* @return the resolved arguments
195
*/
196
Object[] resolve(Class<?>[] parameterTypes);
197
198
/**
199
* Resolve arguments for the given parameter types starting from the specified index.
200
* @param parameterTypes the parameter types
201
* @param startIndex the start index
202
* @return the resolved arguments
203
*/
204
Object[] resolve(Class<?>[] parameterTypes, int startIndex);
205
}
206
207
/**
208
* Code generator for autowired arguments resolution.
209
*/
210
class AutowiredArgumentsCodeGenerator {
211
/**
212
* Create a new AutowiredArgumentsCodeGenerator.
213
* @param className the class name being generated
214
* @param methods the methods that are available
215
*/
216
public AutowiredArgumentsCodeGenerator(ClassName className, MultiStatement methods);
217
218
/**
219
* Generate code to resolve arguments for the given parameter types.
220
* @param parameterTypes the parameter types
221
* @return the generated code block
222
*/
223
public CodeBlock generateCode(Class<?>[] parameterTypes);
224
225
/**
226
* Generate code to resolve arguments for the given parameter types starting from the specified index.
227
* @param parameterTypes the parameter types
228
* @param startIndex the start index
229
* @return the generated code block
230
*/
231
public CodeBlock generateCode(Class<?>[] parameterTypes, int startIndex);
232
233
/**
234
* Generate code to resolve arguments for the given parameter types with a custom variable name.
235
* @param parameterTypes the parameter types
236
* @param startIndex the start index
237
* @param variableName the variable name to use
238
* @return the generated code block
239
*/
240
public CodeBlock generateCode(Class<?>[] parameterTypes, int startIndex, String variableName);
241
}
242
```
243
244
### Bean Registration Code Fragments
245
246
Customizable code fragments for bean registration generation.
247
248
```java { .api }
249
/**
250
* Interface that defines the various code fragments that are used during bean registration code generation.
251
*/
252
interface BeanRegistrationCodeFragments {
253
/**
254
* Return the target class name for the given registered bean.
255
* @param registeredBean the registered bean
256
* @return the target class name
257
*/
258
ClassName getTarget(RegisteredBean registeredBean);
259
260
/**
261
* Generate the instance supplier code.
262
* @param generationContext the generation context
263
* @param beanRegistrationCode the bean registration code
264
* @param instanceSupplierCode the instance supplier code
265
* @return the generated instance supplier code
266
*/
267
CodeBlock generateInstanceSupplierCode(GenerationContext generationContext,
268
BeanRegistrationCode beanRegistrationCode,
269
CodeBlock instanceSupplierCode);
270
271
/**
272
* Generate the return statement for the bean registration method.
273
* @param generationContext the generation context
274
* @param beanRegistrationCode the bean registration code
275
* @return the generated return statement
276
*/
277
CodeBlock generateReturnStatement(GenerationContext generationContext,
278
BeanRegistrationCode beanRegistrationCode);
279
280
/**
281
* Generate the set bean definition properties code.
282
* @param generationContext the generation context
283
* @param beanRegistrationCode the bean registration code
284
* @param assignedVariable the assigned variable name
285
* @param beanDefinition the bean definition
286
* @return the generated properties code
287
*/
288
CodeBlock generateSetBeanDefinitionPropertiesCode(GenerationContext generationContext,
289
BeanRegistrationCode beanRegistrationCode,
290
CodeBlock assignedVariable,
291
BeanDefinition beanDefinition);
292
293
/**
294
* Generate the set bean instance supplier code.
295
* @param generationContext the generation context
296
* @param beanRegistrationCode the bean registration code
297
* @param assignedVariable the assigned variable name
298
* @param instanceSupplierCode the instance supplier code
299
* @return the generated instance supplier code
300
*/
301
CodeBlock generateSetBeanInstanceSupplierCode(GenerationContext generationContext,
302
BeanRegistrationCode beanRegistrationCode,
303
CodeBlock assignedVariable,
304
CodeBlock instanceSupplierCode);
305
}
306
307
/**
308
* A BeanRegistrationCodeFragments decorator implementation.
309
*/
310
class BeanRegistrationCodeFragmentsDecorator implements BeanRegistrationCodeFragments {
311
/**
312
* Create a new BeanRegistrationCodeFragmentsDecorator.
313
* @param delegate the delegate to use
314
*/
315
public BeanRegistrationCodeFragmentsDecorator(BeanRegistrationCodeFragments delegate);
316
317
/**
318
* Return the target class name for the given registered bean.
319
* @param registeredBean the registered bean
320
* @return the target class name
321
*/
322
public ClassName getTarget(RegisteredBean registeredBean);
323
324
/**
325
* Generate the instance supplier code.
326
* @param generationContext the generation context
327
* @param beanRegistrationCode the bean registration code
328
* @param instanceSupplierCode the instance supplier code
329
* @return the generated instance supplier code
330
*/
331
public CodeBlock generateInstanceSupplierCode(GenerationContext generationContext,
332
BeanRegistrationCode beanRegistrationCode,
333
CodeBlock instanceSupplierCode);
334
335
/**
336
* Generate the return statement for the bean registration method.
337
* @param generationContext the generation context
338
* @param beanRegistrationCode the bean registration code
339
* @return the generated return statement
340
*/
341
public CodeBlock generateReturnStatement(GenerationContext generationContext,
342
BeanRegistrationCode beanRegistrationCode);
343
344
/**
345
* Generate the set bean definition properties code.
346
* @param generationContext the generation context
347
* @param beanRegistrationCode the bean registration code
348
* @param assignedVariable the assigned variable name
349
* @param beanDefinition the bean definition
350
* @return the generated properties code
351
*/
352
public CodeBlock generateSetBeanDefinitionPropertiesCode(GenerationContext generationContext,
353
BeanRegistrationCode beanRegistrationCode,
354
CodeBlock assignedVariable,
355
BeanDefinition beanDefinition);
356
357
/**
358
* Generate the set bean instance supplier code.
359
* @param generationContext the generation context
360
* @param beanRegistrationCode the bean registration code
361
* @param assignedVariable the assigned variable name
362
* @param instanceSupplierCode the instance supplier code
363
* @return the generated instance supplier code
364
*/
365
public CodeBlock generateSetBeanInstanceSupplierCode(GenerationContext generationContext,
366
BeanRegistrationCode beanRegistrationCode,
367
CodeBlock assignedVariable,
368
CodeBlock instanceSupplierCode);
369
}
370
```
371
372
### Code Warnings and Deprecation Support
373
374
Support for tracking and suppressing warnings in generated code.
375
376
```java { .api }
377
/**
378
* Utility class for tracking and managing code warnings during AOT processing.
379
*/
380
class CodeWarnings {
381
/**
382
* Create a new CodeWarnings instance.
383
*/
384
public CodeWarnings();
385
386
/**
387
* Register a warning message.
388
* @param warning the warning message
389
*/
390
public void register(String warning);
391
392
/**
393
* Detect deprecation warnings for the given annotated elements.
394
* @param elements the annotated elements to check
395
* @return this CodeWarnings instance for method chaining
396
*/
397
public CodeWarnings detectDeprecation(AnnotatedElement... elements);
398
399
/**
400
* Detect deprecation warnings for the given stream of annotated elements.
401
* @param elements the stream of annotated elements to check
402
* @return this CodeWarnings instance for method chaining
403
*/
404
public CodeWarnings detectDeprecation(Stream<AnnotatedElement> elements);
405
406
/**
407
* Detect deprecation warnings for the given resolvable type.
408
* @param resolvableType the resolvable type to check
409
* @return this CodeWarnings instance for method chaining
410
*/
411
public CodeWarnings detectDeprecation(ResolvableType resolvableType);
412
413
/**
414
* Suppress warnings on the given method specification builder.
415
* @param method the method specification builder
416
*/
417
public void suppress(MethodSpec.Builder method);
418
419
/**
420
* Suppress warnings on the given type specification builder.
421
* @param type the type specification builder
422
*/
423
public void suppress(TypeSpec.Builder type);
424
425
/**
426
* Check if there are any warnings registered.
427
* @return true if there are warnings
428
*/
429
public boolean hasWarnings();
430
431
/**
432
* Return a string representation of all warnings.
433
* @return the warnings as a string
434
*/
435
public String toString();
436
}
437
```
438
439
### Bean Registration Exclusion Filter
440
441
Interface for excluding beans from AOT processing.
442
443
```java { .api }
444
/**
445
* Filter that can be used to exclude bean definitions from AOT processing.
446
*/
447
interface BeanRegistrationExcludeFilter {
448
/**
449
* Determine if the given registered bean should be excluded from AOT processing.
450
* @param registeredBean the registered bean to check
451
* @return true if the bean should be excluded from AOT processing
452
*/
453
boolean isExcluded(RegisteredBean registeredBean);
454
}
455
```
456
457
### AOT Exception Handling
458
459
Exception classes for AOT processing errors.
460
461
```java { .api }
462
/**
463
* Abstract base class for AOT processing related exceptions.
464
*/
465
abstract class AotException extends RuntimeException {
466
/**
467
* Create a new AotException with the specified message.
468
* @param msg the detail message
469
*/
470
public AotException(String msg);
471
472
/**
473
* Create a new AotException with the specified message and root cause.
474
* @param msg the detail message
475
* @param cause the root cause
476
*/
477
public AotException(String msg, Throwable cause);
478
}
479
480
/**
481
* Exception thrown when AOT processing fails.
482
*/
483
class AotProcessingException extends AotException {
484
/**
485
* Create a new AotProcessingException with the specified message.
486
* @param msg the detail message
487
*/
488
public AotProcessingException(String msg);
489
490
/**
491
* Create a new AotProcessingException with the specified message and root cause.
492
* @param msg the detail message
493
* @param cause the root cause
494
*/
495
public AotProcessingException(String msg, Throwable cause);
496
}
497
498
/**
499
* Exception thrown when bean processing fails during AOT.
500
*/
501
class AotBeanProcessingException extends AotException {
502
private final RootBeanDefinition beanDefinition;
503
504
/**
505
* Create a new AotBeanProcessingException for the given bean definition.
506
* @param beanDefinition the bean definition that failed processing
507
* @param msg the detail message
508
*/
509
public AotBeanProcessingException(RootBeanDefinition beanDefinition, String msg);
510
511
/**
512
* Create a new AotBeanProcessingException for the given bean definition.
513
* @param beanDefinition the bean definition that failed processing
514
* @param msg the detail message
515
* @param cause the root cause
516
*/
517
public AotBeanProcessingException(RootBeanDefinition beanDefinition, String msg, Throwable cause);
518
519
/**
520
* Return the bean definition that failed processing.
521
* @return the bean definition
522
*/
523
public RootBeanDefinition getBeanDefinition();
524
}
525
```
526
527
**Usage Examples:**
528
529
```java
530
import org.springframework.aot.generate.GenerationContext;
531
import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor;
532
import org.springframework.beans.factory.aot.BeanRegistrationAotContribution;
533
import org.springframework.beans.factory.support.RegisteredBean;
534
535
// Custom AOT processor example
536
public class CustomBeanRegistrationAotProcessor implements BeanRegistrationAotProcessor {
537
538
@Override
539
public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
540
// Only process beans of specific types
541
if (!isProcessable(registeredBean)) {
542
return null;
543
}
544
545
return new CustomBeanRegistrationAotContribution(registeredBean);
546
}
547
548
private boolean isProcessable(RegisteredBean registeredBean) {
549
Class<?> beanClass = registeredBean.getBeanClass();
550
return MyProcessableInterface.class.isAssignableFrom(beanClass);
551
}
552
553
private static class CustomBeanRegistrationAotContribution implements BeanRegistrationAotContribution {
554
private final RegisteredBean registeredBean;
555
556
public CustomBeanRegistrationAotContribution(RegisteredBean registeredBean) {
557
this.registeredBean = registeredBean;
558
}
559
560
@Override
561
public void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) {
562
// Generate custom initialization code
563
CodeBlock customCode = CodeBlock.builder()
564
.addStatement("$T bean = $L", registeredBean.getBeanClass(), "instanceSupplier.get()")
565
.addStatement("bean.initializeForAot()")
566
.addStatement("return bean")
567
.build();
568
569
// Apply the custom code to the registration
570
beanRegistrationCode.getInstanceSupplierCodeGenerator().addCode(customCode);
571
}
572
}
573
}
574
575
// Bean factory initialization AOT processor example
576
public class CustomBeanFactoryInitializationAotProcessor implements BeanFactoryInitializationAotProcessor {
577
578
@Override
579
public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory) {
580
// Check if we need to contribute initialization code
581
if (!needsCustomInitialization(beanFactory)) {
582
return null;
583
}
584
585
return new CustomBeanFactoryInitializationAotContribution();
586
}
587
588
private boolean needsCustomInitialization(ConfigurableListableBeanFactory beanFactory) {
589
// Check for specific beans or configuration that requires custom initialization
590
return beanFactory.containsBean("customConfigurationBean");
591
}
592
593
private static class CustomBeanFactoryInitializationAotContribution implements BeanFactoryInitializationAotContribution {
594
595
@Override
596
public void applyTo(GenerationContext generationContext, BeanFactoryInitializationCode beanFactoryInitializationCode) {
597
// Generate custom bean factory initialization code
598
MethodSpec initMethod = MethodSpec.methodBuilder("initializeCustomConfiguration")
599
.addModifiers(Modifier.PRIVATE, Modifier.STATIC)
600
.addParameter(ConfigurableListableBeanFactory.class, "beanFactory")
601
.addStatement("// Custom initialization logic here")
602
.addStatement("$T customBean = beanFactory.getBean($S, $T.class)",
603
CustomConfigBean.class, "customConfigurationBean", CustomConfigBean.class)
604
.addStatement("customBean.performAotInitialization()")
605
.build();
606
607
beanFactoryInitializationCode.getTypeBuilder().addMethod(initMethod);
608
}
609
}
610
}
611
612
// Bean exclusion filter example
613
public class CustomBeanRegistrationExcludeFilter implements BeanRegistrationExcludeFilter {
614
615
@Override
616
public boolean isExcluded(RegisteredBean registeredBean) {
617
// Exclude prototype beans from AOT processing
618
if (registeredBean.getBeanDefinition().isPrototype()) {
619
return true;
620
}
621
622
// Exclude beans with specific annotations
623
Class<?> beanClass = registeredBean.getBeanClass();
624
if (beanClass.isAnnotationPresent(ExcludeFromAot.class)) {
625
return true;
626
}
627
628
// Exclude test-related beans
629
String packageName = beanClass.getPackage().getName();
630
if (packageName.contains(".test.") || packageName.endsWith(".test")) {
631
return true;
632
}
633
634
return false;
635
}
636
}
637
638
// Custom annotation for excluding beans from AOT
639
@Target(ElementType.TYPE)
640
@Retention(RetentionPolicy.RUNTIME)
641
@Documented
642
public @interface ExcludeFromAot {
643
String reason() default "";
644
}
645
646
// Usage in Spring configuration
647
@Configuration
648
public class AotProcessingConfiguration {
649
650
@Bean
651
public BeanRegistrationAotProcessor customBeanRegistrationAotProcessor() {
652
return new CustomBeanRegistrationAotProcessor();
653
}
654
655
@Bean
656
public BeanFactoryInitializationAotProcessor customBeanFactoryInitializationAotProcessor() {
657
return new CustomBeanFactoryInitializationAotProcessor();
658
}
659
660
@Bean
661
public BeanRegistrationExcludeFilter customBeanRegistrationExcludeFilter() {
662
return new CustomBeanRegistrationExcludeFilter();
663
}
664
}
665
```
666
667
### Code Generation Utilities
668
669
Utilities for working with code generation during AOT processing.
670
671
```java { .api }
672
/**
673
* Enumeration of different sources for AOT processing.
674
*/
675
enum Source {
676
/** Source from Spring factories. */
677
SPRING_FACTORIES,
678
/** Source from bean factory. */
679
BEAN_FACTORY;
680
681
/**
682
* Create a loader for Spring factories.
683
* @return the loader
684
*/
685
public static Loader factories();
686
687
/**
688
* Create a loader for Spring factories with a specific ClassLoader.
689
* @param classLoader the ClassLoader to use
690
* @return the loader
691
*/
692
public static Loader factories(ClassLoader classLoader);
693
694
/**
695
* Create a loader for Spring factories with a specific SpringFactoriesLoader.
696
* @param springFactoriesLoader the SpringFactoriesLoader to use
697
* @return the loader
698
*/
699
public static Loader factories(SpringFactoriesLoader springFactoriesLoader);
700
701
/**
702
* Create a loader for both Spring factories and beans.
703
* @param beanFactory the bean factory
704
* @return the loader
705
*/
706
public static Loader factoriesAndBeans(ListableBeanFactory beanFactory);
707
708
/**
709
* Create a loader for both Spring factories and beans.
710
* @param springFactoriesLoader the SpringFactoriesLoader to use
711
* @param beanFactory the bean factory
712
* @return the loader
713
*/
714
public static Loader factoriesAndBeans(SpringFactoriesLoader springFactoriesLoader, ListableBeanFactory beanFactory);
715
716
/**
717
* Loader interface for loading instances from different sources.
718
*/
719
interface Loader<T> extends Iterable<T> {
720
/**
721
* Return an iterator over the loaded instances.
722
* @return the iterator
723
*/
724
Iterator<T> iterator();
725
726
/**
727
* Return a stream of the loaded instances.
728
* @return the stream
729
*/
730
Stream<T> stream();
731
732
/**
733
* Return the loaded instances as a list.
734
* @return the list of instances
735
*/
736
List<T> asList();
737
}
738
739
/** The location of the AOT factories resource. */
740
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring/aot.factories";
741
}
742
```