You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
on any Spring bean or `@Bean` factory method. `RuntimeHintsRegistrar` implementations are
610
+
detected and invoked at build time.
608
611
609
612
include-code::./SpellCheckService[]
610
613
@@ -620,8 +623,10 @@ It is also possible to register an implementation statically by adding an entry
620
623
{spring-framework-api}/aot/hint/annotation/Reflective.html[`@Reflective`] provides an idiomatic way to flag the need for reflection on an annotated element.
621
624
For instance, `@EventListener` is meta-annotated with `@Reflective` since the underlying implementation invokes the annotated method using reflection.
622
625
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:
625
630
626
631
include-code::./MyConfiguration[]
627
632
@@ -638,18 +643,18 @@ An example of such customization is covered in the next section.
638
643
[[aot.hints.register-reflection]]
639
644
=== `@RegisterReflection`
640
645
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.
642
647
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`.
644
649
645
650
In the following example, public constructors and public methods can be invoked via reflection on `AccountService`:
`@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.
650
655
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.
653
658
A typical use case is the use of DTOs that the container cannot infer, such as using a web client within a method body.
654
659
655
660
The following example registers `Order` for serialization.
@@ -660,11 +665,66 @@ This registers hints for constructors, fields, properties, and record components
660
665
Hints are also registered for types transitively used on properties and record components.
661
666
In other words, if `Order` exposes others types, hints are registered for those as well.
662
667
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) {
@@ -128,16 +130,17 @@ field signature. The following listing shows the interface definition of `Generi
128
130
----
129
131
130
132
To implement a `GenericConverter`, have `getConvertibleTypes()` return the supported
131
-
source->target type pairs. Then implement `convert(Object, TypeDescriptor,
133
+
source → target type pairs. Then implement `convert(Object, TypeDescriptor,
132
134
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.
135
138
136
139
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.
141
144
142
145
NOTE: Because `GenericConverter` is a more complex SPI interface, you should use
143
146
it only when you need it. Favor `Converter` or `ConverterFactory` for basic type
@@ -148,9 +151,9 @@ conversion needs.
148
151
=== Using `ConditionalGenericConverter`
149
152
150
153
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.
154
157
`ConditionalGenericConverter` is the union of the `GenericConverter` and
155
158
`ConditionalConverter` interfaces that lets you define such custom matching criteria:
156
159
@@ -212,7 +215,7 @@ creating common `ConversionService` configurations.
212
215
A `ConversionService` is a stateless object designed to be instantiated at application
213
216
startup and then shared between multiple threads. In a Spring application, you typically
214
217
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
216
219
conversion needs to be performed by the framework. You can also inject this
217
220
`ConversionService` into any of your beans and invoke it directly.
218
221
@@ -249,7 +252,8 @@ It is also common to use a `ConversionService` within a Spring MVC application.
249
252
xref:web/webmvc/mvc-config/conversion.adoc[Conversion and Formatting] in the Spring MVC chapter.
250
253
251
254
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`.
0 commit comments