14
14
* limitations under the License.
15
15
*/
16
16
17
- package org .springframework .context . aot ;
17
+ package org .springframework .aot . hint . annotation ;
18
18
19
19
import java .lang .reflect .AnnotatedElement ;
20
20
import java .lang .reflect .Constructor ;
21
21
import java .util .Arrays ;
22
22
import java .util .HashMap ;
23
- import java .util .LinkedHashSet ;
23
+ import java .util .HashSet ;
24
24
import java .util .List ;
25
25
import java .util .Map ;
26
26
import java .util .Set ;
27
27
import java .util .function .Consumer ;
28
28
29
- import org .springframework .aot .generate .GenerationContext ;
30
29
import org .springframework .aot .hint .ReflectionHints ;
31
30
import org .springframework .aot .hint .RuntimeHints ;
32
- import org .springframework .aot .hint .annotation .Reflective ;
33
- import org .springframework .aot .hint .annotation .ReflectiveProcessor ;
34
31
import org .springframework .aot .hint .support .RuntimeHintsUtils ;
35
- import org .springframework .beans .BeanUtils ;
36
- import org .springframework .beans .factory .aot .BeanRegistrationAotContribution ;
37
- import org .springframework .beans .factory .aot .BeanRegistrationAotProcessor ;
38
- import org .springframework .beans .factory .aot .BeanRegistrationCode ;
39
- import org .springframework .beans .factory .support .RegisteredBean ;
40
32
import org .springframework .core .annotation .MergedAnnotation ;
41
33
import org .springframework .core .annotation .MergedAnnotations ;
42
- import org .springframework .lang .Nullable ;
43
34
import org .springframework .util .ClassUtils ;
44
35
import org .springframework .util .ReflectionUtils ;
45
36
46
37
/**
47
- * AOT {@code BeanRegistrationAotProcessor} that detects the presence of
48
- * {@link Reflective @Reflective} on annotated elements and invokes the
49
- * underlying {@link ReflectiveProcessor} implementations.
38
+ * Process {@link Reflective} annotated elements.
50
39
*
51
40
* @author Stephane Nicoll
52
- * @author Sebastien Deleuze
41
+ * since 6.0
53
42
*/
54
- class ReflectiveProcessorBeanRegistrationAotProcessor implements BeanRegistrationAotProcessor {
43
+ public class ReflectiveRuntimeHintsRegistrar {
55
44
56
45
private final Map <Class <? extends ReflectiveProcessor >, ReflectiveProcessor > processors = new HashMap <>();
57
46
58
- @ Nullable
59
- @ Override
60
- public BeanRegistrationAotContribution processAheadOfTime (RegisteredBean registeredBean ) {
61
- Class <?> beanClass = registeredBean .getBeanClass ();
62
- Set <Entry > entries = new LinkedHashSet <>();
63
- processType (entries , beanClass );
64
- for (Class <?> implementedInterface : ClassUtils .getAllInterfacesForClass (beanClass )) {
65
- processType (entries , implementedInterface );
66
- }
67
- if (!entries .isEmpty ()) {
68
- return new ReflectiveProcessorBeanRegistrationAotContribution (entries );
47
+
48
+ /**
49
+ * Register the relevant runtime hints for elements that are annotated with
50
+ * {@link Reflective}.
51
+ * @param runtimeHints the runtime hints instance to use
52
+ * @param types the types to process
53
+ */
54
+ public void registerRuntimeHints (RuntimeHints runtimeHints , Class <?>... types ) {
55
+ Set <Entry > entries = new HashSet <>();
56
+ Arrays .stream (types ).forEach (type -> {
57
+ processType (entries , type );
58
+ for (Class <?> implementedInterface : ClassUtils .getAllInterfacesForClass (type )) {
59
+ processType (entries , implementedInterface );
60
+ }
61
+ });
62
+ entries .forEach (entry -> {
63
+ AnnotatedElement element = entry .element ();
64
+ entry .processor ().registerReflectionHints (runtimeHints .reflection (), element );
65
+ registerAnnotationIfNecessary (runtimeHints , element );
66
+ });
67
+ }
68
+
69
+ private void registerAnnotationIfNecessary (RuntimeHints hints , AnnotatedElement element ) {
70
+ MergedAnnotation <Reflective > reflectiveAnnotation = MergedAnnotations .from (element )
71
+ .get (Reflective .class );
72
+ MergedAnnotation <?> metaSource = reflectiveAnnotation .getMetaSource ();
73
+ if (metaSource != null ) {
74
+ RuntimeHintsUtils .registerAnnotationIfNecessary (hints , metaSource );
69
75
}
70
- return null ;
71
76
}
72
77
73
78
private void processType (Set <Entry > entries , Class <?> typeToProcess ) {
@@ -99,13 +104,22 @@ private Entry createEntry(AnnotatedElement element) {
99
104
Class <? extends ReflectiveProcessor >[] processorClasses = (Class <? extends ReflectiveProcessor >[])
100
105
MergedAnnotations .from (element , MergedAnnotations .SearchStrategy .TYPE_HIERARCHY ).get (Reflective .class ).getClassArray ("value" );
101
106
List <ReflectiveProcessor > processors = Arrays .stream (processorClasses ).distinct ()
102
- .map (processorClass -> this .processors .computeIfAbsent (processorClass , BeanUtils ::instantiateClass ))
107
+ .map (processorClass -> this .processors .computeIfAbsent (processorClass , this ::instantiateClass ))
103
108
.toList ();
104
109
ReflectiveProcessor processorToUse = (processors .size () == 1 ? processors .get (0 )
105
110
: new DelegateReflectiveProcessor (processors ));
106
111
return new Entry (element , processorToUse );
107
112
}
108
113
114
+ private ReflectiveProcessor instantiateClass (Class <? extends ReflectiveProcessor > type ) {
115
+ try {
116
+ return type .getDeclaredConstructor ().newInstance ();
117
+ }
118
+ catch (Exception ex ) {
119
+ throw new IllegalStateException ("Failed to instantiate " + type , ex );
120
+ }
121
+ }
122
+
109
123
static class DelegateReflectiveProcessor implements ReflectiveProcessor {
110
124
111
125
private final Iterable <ReflectiveProcessor > processors ;
@@ -123,33 +137,4 @@ public void registerReflectionHints(ReflectionHints hints, AnnotatedElement elem
123
137
124
138
private record Entry (AnnotatedElement element , ReflectiveProcessor processor ) {}
125
139
126
- private static class ReflectiveProcessorBeanRegistrationAotContribution implements BeanRegistrationAotContribution {
127
-
128
- private final Iterable <Entry > entries ;
129
-
130
- public ReflectiveProcessorBeanRegistrationAotContribution (Iterable <Entry > entries ) {
131
- this .entries = entries ;
132
- }
133
-
134
- @ Override
135
- public void applyTo (GenerationContext generationContext , BeanRegistrationCode beanRegistrationCode ) {
136
- RuntimeHints runtimeHints = generationContext .getRuntimeHints ();
137
- this .entries .forEach (entry -> {
138
- AnnotatedElement element = entry .element ();
139
- entry .processor ().registerReflectionHints (runtimeHints .reflection (), element );
140
- registerAnnotationIfNecessary (runtimeHints , element );
141
- });
142
- }
143
-
144
- private void registerAnnotationIfNecessary (RuntimeHints hints , AnnotatedElement element ) {
145
- MergedAnnotation <Reflective > reflectiveAnnotation = MergedAnnotations .from (element )
146
- .get (Reflective .class );
147
- MergedAnnotation <?> metaSource = reflectiveAnnotation .getMetaSource ();
148
- if (metaSource != null ) {
149
- RuntimeHintsUtils .registerAnnotationIfNecessary (hints , metaSource );
150
- }
151
- }
152
-
153
- }
154
-
155
140
}
0 commit comments