Skip to content

Commit 7d394a0

Browse files
committed
Merge branch '6.2.x'
2 parents 197de07 + 983fdeb commit 7d394a0

File tree

2 files changed

+96
-36
lines changed

2 files changed

+96
-36
lines changed

framework-docs/modules/ROOT/pages/core/aot.adoc

Lines changed: 71 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ build time.
271271
While your application may interact with an interface that a bean implements, it is still very important to declare the most precise type.
272272
The AOT engine performs additional checks on the bean type, such as detecting the presence of `@Autowired` members or lifecycle callback methods.
273273

274-
For `@Configuration` classes, make sure that the return type of a `@Bean` factory method is as precise as possible.
274+
For `@Configuration` classes, make sure that the return type of an `@Bean` factory method is as precise as possible.
275275
Consider the following example:
276276

277277
[tabs]
@@ -602,9 +602,12 @@ A number of convenient annotations are also provided for common use cases.
602602
[[aot.hints.import-runtime-hints]]
603603
=== `@ImportRuntimeHints`
604604

605-
`RuntimeHintsRegistrar` implementations allow you to get a callback to the `RuntimeHints` instance managed by the AOT engine.
606-
Implementations of this interface can be registered using `@ImportRuntimeHints` on any Spring bean or `@Bean` factory method.
607-
`RuntimeHintsRegistrar` implementations are detected and invoked at build time.
605+
{spring-framework-api}/aot/hint/RuntimeHintsRegistrar.html[`RuntimeHintsRegistrar`]
606+
implementations allow you to get a callback to the `RuntimeHints` instance managed by the
607+
AOT engine. Implementations of this interface can be registered using
608+
{spring-framework-api}/context/annotation/ImportRuntimeHints.html[`@ImportRuntimeHints`]
609+
on any Spring bean or `@Bean` factory method. `RuntimeHintsRegistrar` implementations are
610+
detected and invoked at build time.
608611

609612
include-code::./SpellCheckService[]
610613

@@ -620,8 +623,10 @@ It is also possible to register an implementation statically by adding an entry
620623
{spring-framework-api}/aot/hint/annotation/Reflective.html[`@Reflective`] provides an idiomatic way to flag the need for reflection on an annotated element.
621624
For instance, `@EventListener` is meta-annotated with `@Reflective` since the underlying implementation invokes the annotated method using reflection.
622625

623-
Out-of-the-box, only Spring beans are considered, but you can opt-in for scanning using `@ReflectiveScan`.
624-
In the example below, all types in the `com.example.app` package and its subpackages are considered:
626+
Out-of-the-box, only Spring beans are considered, but you can opt-in for scanning using
627+
{spring-framework-api}/context/annotation/ReflectiveScan.html[`@ReflectiveScan`]. In the
628+
example below, all types in the `com.example.app` package and its subpackages are
629+
considered:
625630

626631
include-code::./MyConfiguration[]
627632

@@ -638,18 +643,18 @@ An example of such customization is covered in the next section.
638643
[[aot.hints.register-reflection]]
639644
=== `@RegisterReflection`
640645

641-
{spring-framework-api}/aot/hint/annotation/RegisterReflection.html[`@RegisterReflection`] is a specialization of `@Reflective` that provides a declarative way of registering reflection for arbitrary types.
646+
{spring-framework-api}/aot/hint/annotation/RegisterReflection.html[`@RegisterReflection`] is a specialization of `@Reflective` that provides a declarative way to register reflection for arbitrary types.
642647

643-
NOTE: As a specialization of `@Reflective`, this is also detected if you are using `@ReflectiveScan`.
648+
NOTE: As a specialization of `@Reflective`, `@RegisterReflection` is also detected if you are using `@ReflectiveScan`.
644649

645650
In the following example, public constructors and public methods can be invoked via reflection on `AccountService`:
646651

647652
include-code::./MyConfiguration[tag=snippet,indent=0]
648653

649654
`@RegisterReflection` can be applied to any target type at the class level, but it can also be applied directly to a method to better indicate where the hints are actually required.
650655

651-
`@RegisterReflection` can be used as a meta-annotation to provide more specific needs.
652-
{spring-framework-api}/aot/hint/annotation/RegisterReflectionForBinding.html[`@RegisterReflectionForBinding`] is such composed annotation and registers the need for serializing arbitrary types.
656+
`@RegisterReflection` can be used as a meta-annotation to support more specific needs.
657+
{spring-framework-api}/aot/hint/annotation/RegisterReflectionForBinding.html[`@RegisterReflectionForBinding`] is a composed annotation that is meta-annotated with `@RegisterReflection` and registers the need for serializing arbitrary types.
653658
A typical use case is the use of DTOs that the container cannot infer, such as using a web client within a method body.
654659

655660
The following example registers `Order` for serialization.
@@ -660,11 +665,66 @@ This registers hints for constructors, fields, properties, and record components
660665
Hints are also registered for types transitively used on properties and record components.
661666
In other words, if `Order` exposes others types, hints are registered for those as well.
662667

668+
[[aot.hints.convention-based-conversion]]
669+
=== Runtime Hints for Convention-based Conversion
670+
671+
Although the core container provides built-in support for automatic conversion of many
672+
common types (see xref:core/validation/convert.adoc[Spring Type Conversion]), some
673+
conversions are supported via a convention-based algorithm that relies on reflection.
674+
675+
Specifically, if there is no explicit `Converter` registered with the `ConversionService`
676+
for a particular source → target type pair, the internal `ObjectToObjectConverter`
677+
will attempt to use conventions to convert a source object to a target type by delegating
678+
to a method on the source object or to a static factory method or constructor on the
679+
target type. Since this convention-based algorithm can be applied to arbitrary types at
680+
runtime, the core container is not able to infer the runtime hints necessary to support
681+
such reflection.
682+
683+
If you encounter convention-based conversion issues within a native image resulting from
684+
lacking runtime hints, you can register the necessary hints programmatically. For
685+
example, if your application requires a conversion from `java.time.Instant` to
686+
`java.sql.Timestamp` and relies on `ObjectToObjectConverter` to invoke
687+
`java.sql.Timestamp.from(Instant)` using reflection, you could implement a custom
688+
`RuntimeHintsRegitrar` to support this use case within a native image, as demonstrated in
689+
the following example.
690+
691+
[tabs]
692+
======
693+
Java::
694+
+
695+
[source,java,indent=0,subs="verbatim,quotes"]
696+
----
697+
public class TimestampConversionRuntimeHints implements RuntimeHintsRegistrar {
698+
699+
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
700+
ReflectionHints reflectionHints = hints.reflection();
701+
702+
reflectionHints.registerTypeIfPresent(classLoader, "java.sql.Timestamp", hint -> hint
703+
.withMethod("from", List.of(TypeReference.of(Instant.class)), ExecutableMode.INVOKE)
704+
.onReachableType(TypeReference.of("java.sql.Timestamp")));
705+
}
706+
}
707+
----
708+
======
709+
710+
`TimestampConversionRuntimeHints` can then be registered declaratively via
711+
<<aot.hints.import-runtime-hints>> or statically via a `META-INF/spring/aot.factories`
712+
configuration file.
713+
714+
[NOTE]
715+
====
716+
The above `TimestampConversionRuntimeHints` class is a simplified version of the
717+
`ObjectToObjectConverterRuntimeHints` class that is included in the framework and
718+
registered by default.
719+
720+
Thus, this specific `Instant`-to-`Timestamp` use case is already handled by the framework.
721+
====
722+
663723
[[aot.hints.testing]]
664724
=== Testing Runtime Hints
665725

666726
Spring Core also ships `RuntimeHintsPredicates`, a utility for checking that existing hints match a particular use case.
667-
This can be used in your own tests to validate that a `RuntimeHintsRegistrar` contains the expected results.
727+
This can be used in your own tests to validate that a `RuntimeHintsRegistrar` produces the expected results.
668728
We can write a test for our `SpellCheckService` and ensure that we will be able to load a dictionary at runtime:
669729

670730
include-code::./SpellCheckServiceTests[tag=hintspredicates]

framework-docs/modules/ROOT/pages/core/validation/convert.adoc

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,9 @@ When you need to centralize the conversion logic for an entire class hierarchy
7272
}
7373
----
7474

75-
Parameterize S to be the type you are converting from and R to be the base type defining
75+
Parameterize `S` to be the type you are converting from and `R` to be the base type defining
7676
the __range__ of classes you can convert to. Then implement `getConverter(Class<T>)`,
77-
where T is a subclass of R.
77+
where `T` is a subclass of `R`.
7878

7979
Consider the `StringToEnumConverterFactory` as an example:
8080

@@ -107,13 +107,15 @@ Consider the `StringToEnumConverterFactory` as an example:
107107
[[core-convert-GenericConverter-SPI]]
108108
== Using `GenericConverter`
109109

110-
When you require a sophisticated `Converter` implementation, consider using the
111-
`GenericConverter` interface. With a more flexible but less strongly typed signature
112-
than `Converter`, a `GenericConverter` supports converting between multiple source and
113-
target types. In addition, a `GenericConverter` makes available source and target field
114-
context that you can use when you implement your conversion logic. Such context lets a
115-
type conversion be driven by a field annotation or by generic information declared on a
116-
field signature. The following listing shows the interface definition of `GenericConverter`:
110+
When you require a more sophisticated `Converter` implementation, consider using the
111+
`GenericConverter` interface. With a more flexible but less strongly typed signature than
112+
`Converter`, a `GenericConverter` supports converting between multiple source and target
113+
types. In addition, a `GenericConverter` is provided source and target type descriptors
114+
that you can use when you implement your conversion logic. Such type descriptors enable
115+
type conversion to be driven by an annotation on the source of the descriptor (such as a
116+
field or method) or by generic information declared in a field signature, method
117+
signature, etc. The following listing shows the definition of the `GenericConverter`
118+
interface:
117119

118120
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
119121
----
@@ -128,16 +130,17 @@ field signature. The following listing shows the interface definition of `Generi
128130
----
129131

130132
To implement a `GenericConverter`, have `getConvertibleTypes()` return the supported
131-
source->target type pairs. Then implement `convert(Object, TypeDescriptor,
133+
source &#8594; target type pairs. Then implement `convert(Object, TypeDescriptor,
132134
TypeDescriptor)` to contain your conversion logic. The source `TypeDescriptor` provides
133-
access to the source field that holds the value being converted. The target `TypeDescriptor`
134-
provides access to the target field where the converted value is to be set.
135+
access to the source field or method that holds the value being converted. The target
136+
`TypeDescriptor` provides access to the target field or method where the converted value
137+
is to be set.
135138

136139
A good example of a `GenericConverter` is a converter that converts between a Java array
137-
and a collection. Such an `ArrayToCollectionConverter` introspects the field that declares
138-
the target collection type to resolve the collection's element type. This lets each
139-
element in the source array be converted to the collection element type before the
140-
collection is set on the target field.
140+
and a collection. Such an `ArrayToCollectionConverter` introspects the field or method
141+
that declares the target collection type to resolve the collection's element type. This
142+
lets each element in the source array be converted to the collection element type before
143+
the collection is set on the target field or supplied to the target method or constructor.
141144

142145
NOTE: Because `GenericConverter` is a more complex SPI interface, you should use
143146
it only when you need it. Favor `Converter` or `ConverterFactory` for basic type
@@ -148,9 +151,9 @@ conversion needs.
148151
=== Using `ConditionalGenericConverter`
149152

150153
Sometimes, you want a `Converter` to run only if a specific condition holds true. For
151-
example, you might want to run a `Converter` only if a specific annotation is present
152-
on the target field, or you might want to run a `Converter` only if a specific method
153-
(such as a `static valueOf` method) is defined on the target class.
154+
example, you might want to run a `Converter` only if a specific annotation is present on
155+
the target field or method, or you might want to run a `Converter` only if a specific
156+
method (such as a `static valueOf` method) is defined on the target type.
154157
`ConditionalGenericConverter` is the union of the `GenericConverter` and
155158
`ConditionalConverter` interfaces that lets you define such custom matching criteria:
156159

@@ -212,7 +215,7 @@ creating common `ConversionService` configurations.
212215
A `ConversionService` is a stateless object designed to be instantiated at application
213216
startup and then shared between multiple threads. In a Spring application, you typically
214217
configure a `ConversionService` instance for each Spring container (or `ApplicationContext`).
215-
Spring picks up that `ConversionService` and uses it whenever a type
218+
Spring picks up that `ConversionService` and uses it whenever type
216219
conversion needs to be performed by the framework. You can also inject this
217220
`ConversionService` into any of your beans and invoke it directly.
218221

@@ -249,7 +252,8 @@ It is also common to use a `ConversionService` within a Spring MVC application.
249252
xref:web/webmvc/mvc-config/conversion.adoc[Conversion and Formatting] in the Spring MVC chapter.
250253

251254
In certain situations, you may wish to apply formatting during conversion. See
252-
xref:core/validation/format.adoc#format-FormatterRegistry-SPI[The `FormatterRegistry` SPI] for details on using `FormattingConversionServiceFactoryBean`.
255+
xref:core/validation/format.adoc#format-FormatterRegistry-SPI[The `FormatterRegistry` SPI]
256+
for details on using `FormattingConversionServiceFactoryBean`.
253257

254258

255259

@@ -338,7 +342,3 @@ method on the `DefaultConversionService` class.
338342
Converters for value types are reused for arrays and collections, so there is
339343
no need to create a specific converter to convert from a `Collection` of `S` to a
340344
`Collection` of `T`, assuming that standard collection handling is appropriate.
341-
342-
343-
344-

0 commit comments

Comments
 (0)