Review AOT recommendations in the reference guide
This commit focuses on improving the AOT section on programmatic registration of additional beans. This makes it more clear that a `BeanDefinitionRegistry` must be used and that singletons are not processed. Closes gh-32240 Closes gh-32241
This commit is contained in:
parent
750cb73902
commit
c46d6286ee
|
@ -17,8 +17,11 @@ Applying such optimizations early implies the following restrictions:
|
||||||
* The beans defined in your application cannot change at runtime, meaning:
|
* The beans defined in your application cannot change at runtime, meaning:
|
||||||
** `@Profile`, in particular profile-specific configuration needs to be chosen at build time.
|
** `@Profile`, in particular profile-specific configuration needs to be chosen at build time.
|
||||||
** `Environment` properties that impact the presence of a bean (`@Conditional`) are only considered at build time.
|
** `Environment` properties that impact the presence of a bean (`@Conditional`) are only considered at build time.
|
||||||
* Bean definitions with instance suppliers (lambdas or method references) cannot be transformed ahead-of-time (see related {spring-framework-issues}/29555[spring-framework#29555] issue).
|
* Bean definitions with instance suppliers (lambdas or method references) cannot be transformed ahead-of-time
|
||||||
* Make sure that the bean type is as precise as possible.
|
* Beans registered as singletons (using `registerSingleton`, typically from
|
||||||
|
`ConfigurableListableBeanFactory`) cannot be transformed ahead-of-time either.
|
||||||
|
* As we can't rely on the instance, make sure that the bean type is as precise as
|
||||||
|
possible.
|
||||||
|
|
||||||
TIP: See also the xref:core/aot.adoc#aot.bestpractices[] section.
|
TIP: See also the xref:core/aot.adoc#aot.bestpractices[] section.
|
||||||
|
|
||||||
|
@ -35,7 +38,7 @@ We intend to support more JVM-based use cases in future generations.
|
||||||
[[aot.basics]]
|
[[aot.basics]]
|
||||||
== AOT engine overview
|
== AOT engine overview
|
||||||
|
|
||||||
The entry point of the AOT engine for processing an `ApplicationContext` arrangement is `ApplicationContextAotGenerator`. It takes care of the following steps, based on a `GenericApplicationContext` that represents the application to optimize and a {spring-framework-api}/aot/generate/GenerationContext.html[`GenerationContext`]:
|
The entry point of the AOT engine for processing an `ApplicationContext` is `ApplicationContextAotGenerator`. It takes care of the following steps, based on a `GenericApplicationContext` that represents the application to optimize and a {spring-framework-api}/aot/generate/GenerationContext.html[`GenerationContext`]:
|
||||||
|
|
||||||
* Refresh an `ApplicationContext` for AOT processing. Contrary to a traditional refresh, this version only creates bean definitions, not bean instances.
|
* Refresh an `ApplicationContext` for AOT processing. Contrary to a traditional refresh, this version only creates bean definitions, not bean instances.
|
||||||
* Invoke the available `BeanFactoryInitializationAotProcessor` implementations and apply their contributions against the `GenerationContext`.
|
* Invoke the available `BeanFactoryInitializationAotProcessor` implementations and apply their contributions against the `GenerationContext`.
|
||||||
|
@ -67,7 +70,13 @@ include-code::./AotProcessingSample[tag=aotcontext]
|
||||||
In this mode, xref:core/beans/factory-extension.adoc#beans-factory-extension-factory-postprocessors[`BeanFactoryPostProcessor` implementations] are invoked as usual.
|
In this mode, xref:core/beans/factory-extension.adoc#beans-factory-extension-factory-postprocessors[`BeanFactoryPostProcessor` implementations] are invoked as usual.
|
||||||
This includes configuration class parsing, import selectors, classpath scanning, etc.
|
This includes configuration class parsing, import selectors, classpath scanning, etc.
|
||||||
Such steps make sure that the `BeanRegistry` contains the relevant bean definitions for the application.
|
Such steps make sure that the `BeanRegistry` contains the relevant bean definitions for the application.
|
||||||
If bean definitions are guarded by conditions (such as `@Profile`), these are discarded at this stage.
|
If bean definitions are guarded by conditions (such as `@Profile`), these are evaluated
|
||||||
|
and bean definitions that don't match their conditions are discarded at this stage.
|
||||||
|
|
||||||
|
If custom code needs to register extra beans programmatically, make sure that they use
|
||||||
|
`BeanDefinitionRegistry`, and not `BeanFactory` as only bean definitions are taken into
|
||||||
|
account. A good pattern is to implement `ImportBeanDefinitionRegistrar` and register it
|
||||||
|
via an `@Import` on one of your configuration classes.
|
||||||
|
|
||||||
Because this mode does not actually create bean instances, `BeanPostProcessor` implementations are not invoked, except for specific variants that are relevant for AOT processing.
|
Because this mode does not actually create bean instances, `BeanPostProcessor` implementations are not invoked, except for specific variants that are relevant for AOT processing.
|
||||||
These are:
|
These are:
|
||||||
|
@ -207,6 +216,27 @@ However, keep in mind that some optimizations are made at build time based on a
|
||||||
|
|
||||||
This section lists the best practices that make sure your application is ready for AOT.
|
This section lists the best practices that make sure your application is ready for AOT.
|
||||||
|
|
||||||
|
[[aot.bestpractices.bean-registration]]
|
||||||
|
== Programmatic bean registration
|
||||||
|
The AOT engine takes care of the `@Configuration` model, and any callback that might be
|
||||||
|
invoked as part of processing your configuration. If you need to register additional
|
||||||
|
beans programmatically, make sure to use a `BeanDefinitionRegistry` to register
|
||||||
|
bean definitions.
|
||||||
|
|
||||||
|
This can be typically done via a `BeanDefinitionRegistryPostProcessor`. Note that, if it
|
||||||
|
is registered itself as a bean, it will be invoked again at runtime unless you make
|
||||||
|
sure to implement `BeanFactoryInitializationAotProcessor` as well. A more idiomatic
|
||||||
|
way is to implement `ImportBeanDefinitionRegistrar` and register it using `@Import` on
|
||||||
|
one of your configuration classes. This invokes your custom code as part of configuration
|
||||||
|
class parsing.
|
||||||
|
|
||||||
|
If you declare additional beans programmatically using a different callback, there are
|
||||||
|
likely not going to be handled by the AOT engine, and therefore no hints are going to be
|
||||||
|
generated for them. Depending on the environment, those beans may not be registered at
|
||||||
|
all. For instance, classpath scanning does not work in a native image as there is no
|
||||||
|
notion of classpath. For cases like this, it is crucial that the scanning happens at
|
||||||
|
build time.
|
||||||
|
|
||||||
[[aot.bestpractices.bean-type]]
|
[[aot.bestpractices.bean-type]]
|
||||||
=== Expose The Most Precise Bean Type
|
=== Expose The Most Precise Bean Type
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue