This chapter covers Spring's Ahead of Time (AOT) optimizations.
This chapter covers Spring's Ahead of Time (AOT) optimizations.
For AOT support specific to integration tests, see xref:testing/testcontext-framework/aot.adoc[Ahead of Time Support for Tests].
For AOT support specific to integration tests, see xref:testing/testcontext-framework/aot.adoc[Ahead of Time Support for Tests].
[[core.aot.introduction]]
[[aot.introduction]]
== Introduction to Ahead of Time Optimizations
== Introduction to Ahead of Time Optimizations
Spring's support for AOT optimizations is meant to inspect an `ApplicationContext` at build time and apply decisions and discovery logic that usually happens at runtime.
Spring's support for AOT optimizations is meant to inspect an `ApplicationContext` at build time and apply decisions and discovery logic that usually happens at runtime.
@ -30,7 +30,7 @@ A Spring AOT processed application typically generates:
NOTE: At the moment, AOT is focused on allowing Spring applications to be deployed as native images using GraalVM.
NOTE: At the moment, AOT is focused on allowing Spring applications to be deployed as native images using GraalVM.
We intend to support more JVM-based use cases in future generations.
We intend to support more JVM-based use cases in future generations.
[[core.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 {api-spring-framework}/aot/generate/GenerationContext.html[`GenerationContext`]:
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 {api-spring-framework}/aot/generate/GenerationContext.html[`GenerationContext`]:
@ -46,7 +46,7 @@ The `RuntimeHints` instance can also be used to generate the relevant GraalVM na
Those steps are covered in greater detail in the sections below.
Those steps are covered in greater detail in the sections below.
[[core.aot.refresh]]
[[aot.refresh]]
== Refresh for AOT Processing
== Refresh for AOT Processing
Refresh for AOT processing is supported on all `GenericApplicationContext` implementations.
Refresh for AOT processing is supported on all `GenericApplicationContext` implementations.
@ -54,13 +54,13 @@ An application context is created with any number of entry points, usually in th
Starting this application with the regular runtime involves a number of steps including classpath scanning, configuration class parsing, bean instantiation, and lifecycle callback handling.
Starting this application with the regular runtime involves a number of steps including classpath scanning, configuration class parsing, bean instantiation, and lifecycle callback handling.
Refresh for AOT processing only applies a subset of what happens with a xref:core/beans/introduction.adoc[regular `refresh`].
Refresh for AOT processing only applies a subset of what happens with a xref:core/beans/introduction.adoc[regular `refresh`].
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.
@ -76,7 +76,7 @@ This makes sure to create any proxy that will be required at runtime.
Once this part completes, the `BeanFactory` contains the bean definitions that are necessary for the application to run. It does not trigger bean instantiation but allows the AOT engine to inspect the beans that will be created at runtime.
Once this part completes, the `BeanFactory` contains the bean definitions that are necessary for the application to run. It does not trigger bean instantiation but allows the AOT engine to inspect the beans that will be created at runtime.
Components that want to participate in this step can implement the {api-spring-framework}/beans/factory/aot/BeanFactoryInitializationAotProcessor.html[`BeanFactoryInitializationAotProcessor`] interface.
Components that want to participate in this step can implement the {api-spring-framework}/beans/factory/aot/BeanFactoryInitializationAotProcessor.html[`BeanFactoryInitializationAotProcessor`] interface.
@ -99,7 +99,7 @@ If such a bean is registered using an `@Bean` factory method, ensure the method
====
====
[[core.aot.bean-registration-contributions]]
[[aot.bean-registration-contributions]]
=== Bean Registration AOT Contributions
=== Bean Registration AOT Contributions
A core `BeanFactoryInitializationAotProcessor` implementation is responsible for collecting the necessary contributions for each candidate `BeanDefinition`.
A core `BeanFactoryInitializationAotProcessor` implementation is responsible for collecting the necessary contributions for each candidate `BeanDefinition`.
@ -186,7 +186,7 @@ When a `datasource` instance is required, a `BeanInstanceSupplier` is called.
This supplier invokes the `dataSource()` method on the `dataSourceConfiguration` bean.
This supplier invokes the `dataSource()` method on the `dataSourceConfiguration` bean.
[[core.aot.hints]]
[[aot.hints]]
== Runtime Hints
== Runtime Hints
Running an application as a native image requires additional information compared to a regular JVM runtime.
Running an application as a native image requires additional information compared to a regular JVM runtime.
@ -210,14 +210,14 @@ For cases that the core container cannot infer, you can register such hints prog
A number of convenient annotations are also provided for common use cases.
A number of convenient annotations are also provided for common use cases.
[[core.aot.hints.import-runtime-hints]]
[[aot.hints.import-runtime-hints]]
=== `@ImportRuntimeHints`
=== `@ImportRuntimeHints`
`RuntimeHintsRegistrar` implementations allow you to get a callback to the `RuntimeHints` instance managed by the AOT engine.
`RuntimeHintsRegistrar` implementations allow you to get a callback to the `RuntimeHints` instance managed by the AOT engine.
Implementations of this interface can be registered using `@ImportRuntimeHints` on any Spring bean or `@Bean` factory method.
Implementations of this interface can be registered using `@ImportRuntimeHints` on any Spring bean or `@Bean` factory method.
`RuntimeHintsRegistrar` implementations are detected and invoked at build time.
`RuntimeHintsRegistrar` implementations are detected and invoked at build time.
include-code::SpellCheckService[]
include-code::./SpellCheckService[]
If at all possible, `@ImportRuntimeHints` should be used as close as possible to the component that requires the hints.
If at all possible, `@ImportRuntimeHints` should be used as close as possible to the component that requires the hints.
This way, if the component is not contributed to the `BeanFactory`, the hints won't be contributed either.
This way, if the component is not contributed to the `BeanFactory`, the hints won't be contributed either.
@ -225,7 +225,7 @@ This way, if the component is not contributed to the `BeanFactory`, the hints wo
It is also possible to register an implementation statically by adding an entry in `META-INF/spring/aot.factories` with a key equal to the fully qualified name of the `RuntimeHintsRegistrar` interface.
It is also possible to register an implementation statically by adding an entry in `META-INF/spring/aot.factories` with a key equal to the fully qualified name of the `RuntimeHintsRegistrar` interface.
[[core.aot.hints.reflective]]
[[aot.hints.reflective]]
=== `@Reflective`
=== `@Reflective`
{api-spring-framework}/aot/hint/annotation/Reflective.html[`@Reflective`] provides an idiomatic way to flag the need for reflection on an annotated element.
{api-spring-framework}/aot/hint/annotation/Reflective.html[`@Reflective`] provides an idiomatic way to flag the need for reflection on an annotated element.
@ -239,7 +239,7 @@ Library authors can reuse this annotation for their own purposes.
If components other than Spring beans need to be processed, a `BeanFactoryInitializationAotProcessor` can detect the relevant types and use `ReflectiveRuntimeHintsRegistrar` to process them.
If components other than Spring beans need to be processed, a `BeanFactoryInitializationAotProcessor` can detect the relevant types and use `ReflectiveRuntimeHintsRegistrar` to process them.
{api-spring-framework}/aot/hint/annotation/RegisterReflectionForBinding.html[`@RegisterReflectionForBinding`] is a specialization of `@Reflective` that registers the need for serializing arbitrary types.
{api-spring-framework}/aot/hint/annotation/RegisterReflectionForBinding.html[`@RegisterReflectionForBinding`] is a specialization of `@Reflective` that registers the need for serializing arbitrary types.
@ -262,14 +262,14 @@ The following example registers `Account` for serialization.
}
}
----
----
[[core.aot.hints.testing]]
[[aot.hints.testing]]
=== Testing Runtime Hints
=== Testing Runtime Hints
Spring Core also ships `RuntimeHintsPredicates`, a utility for checking that existing hints match a particular use case.
Spring Core also ships `RuntimeHintsPredicates`, a utility for checking that existing hints match a particular use case.
This can be used in your own tests to validate that a `RuntimeHintsRegistrar` contains the expected results.
This can be used in your own tests to validate that a `RuntimeHintsRegistrar` contains the expected results.
We can write a test for our `SpellCheckService` and ensure that we will be able to load a dictionary at runtime:
We can write a test for our `SpellCheckService` and ensure that we will be able to load a dictionary at runtime:
With `RuntimeHintsPredicates`, we can check for reflection, resource, serialization, or proxy generation hints.
With `RuntimeHintsPredicates`, we can check for reflection, resource, serialization, or proxy generation hints.
This approach works well for unit tests but implies that the runtime behavior of a component is well known.
This approach works well for unit tests but implies that the runtime behavior of a component is well known.
@ -281,11 +281,11 @@ For more targeted discovery and testing, Spring Framework ships a dedicated modu
This module contains the RuntimeHints Agent, a Java agent that records all method invocations that are related to runtime hints and helps you to assert that a given `RuntimeHints` instance covers all recorded invocations.
This module contains the RuntimeHints Agent, a Java agent that records all method invocations that are related to runtime hints and helps you to assert that a given `RuntimeHints` instance covers all recorded invocations.
Let's consider a piece of infrastructure for which we'd like to test the hints we're contributing during the AOT processing phase.
Let's consider a piece of infrastructure for which we'd like to test the hints we're contributing during the AOT processing phase.
include-code::SampleReflection[]
include-code::./SampleReflection[]
We can then write a unit test (no native compilation required) that checks our contributed hints:
We can then write a unit test (no native compilation required) that checks our contributed hints:
This element is detailed in the section on xref:core/beans/annotation-config.adoc[annotation-based container configuration]
This element is detailed in the section on xref:core/beans/annotation-config.adoc[annotation-based container configuration]
.
.
[[core.appendix.xsd-schemas-context-ltw]]
[[xsd-schemas-context-ltw]]
=== Using `<load-time-weaver/>`
=== Using `<load-time-weaver/>`
This element is detailed in the section on xref:core/aop/using-aspectj.adoc#aop-aj-ltw[load-time weaving with AspectJ in the Spring Framework]
This element is detailed in the section on xref:core/aop/using-aspectj.adoc#aop-aj-ltw[load-time weaving with AspectJ in the Spring Framework]
.
.
[[core.appendix.xsd-schemas-context-sc]]
[[xsd-schemas-context-sc]]
=== Using `<spring-configured/>`
=== Using `<spring-configured/>`
This element is detailed in the section on xref:core/aop/using-aspectj.adoc#aop-atconfigurable[using AspectJ to dependency inject domain objects with Spring]
This element is detailed in the section on xref:core/aop/using-aspectj.adoc#aop-atconfigurable[using AspectJ to dependency inject domain objects with Spring]
.
.
[[core.appendix.xsd-schemas-context-mbe]]
[[xsd-schemas-context-mbe]]
=== Using `<mbean-export/>`
=== Using `<mbean-export/>`
This element is detailed in the section on xref:integration/jmx/naming.adoc#jmx-context-mbeanexport[configuring annotation-based MBean export]
This element is detailed in the section on xref:integration/jmx/naming.adoc#jmx-context-mbeanexport[configuring annotation-based MBean export]
@ -606,7 +606,7 @@ This element is detailed in the section on xref:integration/jmx/naming.adoc#jmx-
[[core.appendix.xsd-schemas-beans]]
[[xsd-schemas-beans]]
== The Beans Schema
== The Beans Schema
Last but not least, we have the elements in the `beans` schema. These elements
Last but not least, we have the elements in the `beans` schema. These elements
|Processing time for HTTP server exchanges at the Framework level
|Processing time for HTTP server exchanges at the Framework level
|===
|===
@ -33,7 +33,7 @@ https://micrometer.io/docs/concepts#_naming_meters[to the format preferred by th
(Prometheus, Atlas, Graphite, InfluxDB...).
(Prometheus, Atlas, Graphite, InfluxDB...).
[[integration.observability.concepts]]
[[observability.concepts]]
== Micrometer Observation concepts
== Micrometer Observation concepts
If you are not familiar with Micrometer Observation, here's a quick summary of the new concepts you should know about.
If you are not familiar with Micrometer Observation, here's a quick summary of the new concepts you should know about.
@ -49,7 +49,7 @@ If you are not familiar with Micrometer Observation, here's a quick summary of t
* An `ObservationDocumentation` documents all observations in a particular domain, listing the expected key names and their meaning.
* An `ObservationDocumentation` documents all observations in a particular domain, listing the expected key names and their meaning.
[[integration.observability.config]]
[[observability.config]]
== Configuring Observations
== Configuring Observations
Global configuration options are available at the `ObservationRegistry#observationConfig()` level.
Global configuration options are available at the `ObservationRegistry#observationConfig()` level.
@ -59,33 +59,33 @@ Each instrumented component will provide two extension points:
* providing a custom `ObservationConvention` to change the default observation name and extracted `KeyValues`
* providing a custom `ObservationConvention` to change the default observation name and extracted `KeyValues`
[[integration.observability.config.conventions]]
[[observability.config.conventions]]
=== Using custom Observation conventions
=== Using custom Observation conventions
Let's take the example of the Spring MVC "http.server.requests" metrics instrumentation with the `ServerHttpObservationFilter`.
Let's take the example of the Spring MVC "http.server.requests" metrics instrumentation with the `ServerHttpObservationFilter`.
This observation is using a `ServerRequestObservationConvention` with a `ServerRequestObservationContext`; custom conventions can be configured on the Servlet filter.
This observation is using a `ServerRequestObservationConvention` with a `ServerRequestObservationContext`; custom conventions can be configured on the Servlet filter.
If you would like to customize the metadata produced with the observation, you can extend the `DefaultServerRequestObservationConvention` for your requirements:
If you would like to customize the metadata produced with the observation, you can extend the `DefaultServerRequestObservationConvention` for your requirements:
You can also achieve similar goals using a custom `ObservationFilter` - adding or removing key values for an observation.
You can also achieve similar goals using a custom `ObservationFilter` - adding or removing key values for an observation.
Filters do not replace the default convention and are used as a post-processing component.
Filters do not replace the default convention and are used as a post-processing component.
include-code::ServerRequestObservationFilter[]
include-code::./ServerRequestObservationFilter[]
You can configure `ObservationFilter` instances on the `ObservationRegistry`.
You can configure `ObservationFilter` instances on the `ObservationRegistry`.
[[integration.observability.http-server]]
[[observability.http-server]]
== HTTP Server instrumentation
== HTTP Server instrumentation
HTTP server exchanges observations are created with the name `"http.server.requests"` for Servlet and Reactive applications.
HTTP server exchanges observations are created with the name `"http.server.requests"` for Servlet and Reactive applications.
[[integration.observability.http-server.servlet]]
[[observability.http-server.servlet]]
=== Servlet applications
=== Servlet applications
Applications need to configure the `org.springframework.web.filter.ServerHttpObservationFilter` Servlet filter in their application.
Applications need to configure the `org.springframework.web.filter.ServerHttpObservationFilter` Servlet filter in their application.
@ -95,7 +95,7 @@ This will only record an observation as an error if the `Exception` has not been
Typically, all exceptions handled by Spring MVC's `@ExceptionHandler` and xref:web/webmvc/mvc-ann-rest-exceptions.adoc[`ProblemDetail` support] will not be recorded with the observation.
Typically, all exceptions handled by Spring MVC's `@ExceptionHandler` and xref:web/webmvc/mvc-ann-rest-exceptions.adoc[`ProblemDetail` support] will not be recorded with the observation.
You can, at any point during request processing, set the error field on the `ObservationContext` yourself:
You can, at any point during request processing, set the error field on the `ObservationContext` yourself:
include-code::UserController[]
include-code::./UserController[]
By default, the following `KeyValues` are created:
By default, the following `KeyValues` are created:
@ -118,7 +118,7 @@ By default, the following `KeyValues` are created:
Applications need to configure the `org.springframework.web.filter.reactive.ServerHttpObservationFilter` reactive `WebFilter` in their application.
Applications need to configure the `org.springframework.web.filter.reactive.ServerHttpObservationFilter` reactive `WebFilter` in their application.
@ -128,7 +128,7 @@ This will only record an observation as an error if the `Exception` has not been
Typically, all exceptions handled by Spring WebFlux's `@ExceptionHandler` and xref:web/webflux/ann-rest-exceptions.adoc[`ProblemDetail` support] will not be recorded with the observation.
Typically, all exceptions handled by Spring WebFlux's `@ExceptionHandler` and xref:web/webflux/ann-rest-exceptions.adoc[`ProblemDetail` support] will not be recorded with the observation.
You can, at any point during request processing, set the error field on the `ObservationContext` yourself:
You can, at any point during request processing, set the error field on the `ObservationContext` yourself:
include-code::UserController[]
include-code::./UserController[]
By default, the following `KeyValues` are created:
By default, the following `KeyValues` are created:
@ -152,13 +152,13 @@ By default, the following `KeyValues` are created:
[[integration.observability.http-client]]
[[observability.http-client]]
== HTTP Client instrumentation
== HTTP Client instrumentation
HTTP client exchanges observations are created with the name `"http.client.requests"` for blocking and reactive clients.
HTTP client exchanges observations are created with the name `"http.client.requests"` for blocking and reactive clients.
Unlike their server counterparts, the instrumentation is implemented directly in the client so the only required step is to configure an `ObservationRegistry` on the client.
Unlike their server counterparts, the instrumentation is implemented directly in the client so the only required step is to configure an `ObservationRegistry` on the client.
Applications must configure an `ObservationRegistry` on `RestTemplate` instances to enable the instrumentation; without that, observations are "no-ops".
Applications must configure an `ObservationRegistry` on `RestTemplate` instances to enable the instrumentation; without that, observations are "no-ops".
@ -187,7 +187,7 @@ Instrumentation is using the `org.springframework.http.client.observation.Client
Applications must configure an `ObservationRegistry` on the `WebClient` builder to enable the instrumentation; without that, observations are "no-ops".
Applications must configure an `ObservationRegistry` on the `WebClient` builder to enable the instrumentation; without that, observations are "no-ops".
* `observationRegistry`: the registry to use for enabling xref:integration/observability.adoc#integration.observability.http-client.webclient[Observability support].
* `observationRegistry`: the registry to use for enabling xref:integration/observability.adoc#http-client.webclient[Observability support].
* `observationConvention`: xref:integration/observability.adoc#integration.observability.config[an optional, custom convention to extract metadata] for recorded observations.
* `observationConvention`: xref:integration/observability.adoc#config[an optional, custom convention to extract metadata] for recorded observations.