21
21
import java .lang .annotation .Retention ;
22
22
import java .lang .annotation .RetentionPolicy ;
23
23
import java .lang .annotation .Target ;
24
+ import java .util .function .Consumer ;
24
25
25
26
import org .junit .jupiter .api .Test ;
26
27
28
+ import org .springframework .aot .hint .JdkProxyHint ;
27
29
import org .springframework .aot .hint .MemberCategory ;
30
+ import org .springframework .aot .hint .ReflectionHints ;
28
31
import org .springframework .aot .hint .RuntimeHints ;
32
+ import org .springframework .aot .hint .TypeHint ;
29
33
import org .springframework .aot .hint .TypeReference ;
30
34
import org .springframework .core .annotation .AliasFor ;
31
35
import org .springframework .core .annotation .MergedAnnotations ;
@@ -46,28 +50,49 @@ class RuntimeHintsUtilsTests {
46
50
void registerAnnotation () {
47
51
RuntimeHintsUtils .registerAnnotation (this .hints , MergedAnnotations
48
52
.from (SampleInvokerClass .class ).get (SampleInvoker .class ));
49
- assertThat (this .hints .reflection ().getTypeHint (SampleInvoker .class )).satisfies (typeHint -> {
50
- assertThat (typeHint .constructors ()).isEmpty ();
51
- assertThat (typeHint .fields ()).isEmpty ();
52
- assertThat (typeHint .methods ()).isEmpty ();
53
- assertThat (typeHint .getMemberCategories ()).containsOnly (MemberCategory .INVOKE_PUBLIC_METHODS );
54
- });
53
+ assertThat (this .hints .reflection ().typeHints ()).singleElement ()
54
+ .satisfies (annotationHint (SampleInvoker .class ));
55
55
assertThat (this .hints .proxies ().jdkProxies ()).isEmpty ();
56
56
}
57
57
58
58
@ Test
59
59
void registerAnnotationProxyRegistersJdkProxy () {
60
60
RuntimeHintsUtils .registerAnnotation (this .hints , MergedAnnotations
61
61
.from (RetryInvokerClass .class ).get (RetryInvoker .class ));
62
- assertThat (this .hints .reflection ().getTypeHint (RetryInvoker .class )).satisfies (typeHint -> {
62
+ assertThat (this .hints .reflection ().typeHints ()).singleElement ()
63
+ .satisfies (annotationHint (RetryInvoker .class ));
64
+ assertThat (this .hints .proxies ().jdkProxies ()).singleElement ()
65
+ .satisfies (annotationProxy (RetryInvoker .class ));
66
+ }
67
+
68
+ @ Test
69
+ void registerAnnotationWhereUsedAsAMetaAnnotationRegistersHierarchy () {
70
+ RuntimeHintsUtils .registerAnnotation (this .hints , MergedAnnotations
71
+ .from (RetryWithEnabledFlagInvokerClass .class ).get (SampleInvoker .class ));
72
+ ReflectionHints reflection = this .hints .reflection ();
73
+ assertThat (reflection .typeHints ())
74
+ .anySatisfy (annotationHint (SampleInvoker .class ))
75
+ .anySatisfy (annotationHint (RetryInvoker .class ))
76
+ .anySatisfy (annotationHint (RetryWithEnabledFlagInvoker .class ))
77
+ .hasSize (3 );
78
+ assertThat (this .hints .proxies ().jdkProxies ()).singleElement ()
79
+ .satisfies (annotationProxy (SampleInvoker .class ));
80
+ }
81
+
82
+ private Consumer <TypeHint > annotationHint (Class <?> type ) {
83
+ return typeHint -> {
84
+ assertThat (typeHint .getType ()).isEqualTo (TypeReference .of (type ));
63
85
assertThat (typeHint .constructors ()).isEmpty ();
64
86
assertThat (typeHint .fields ()).isEmpty ();
65
87
assertThat (typeHint .methods ()).isEmpty ();
66
88
assertThat (typeHint .getMemberCategories ()).containsOnly (MemberCategory .INVOKE_PUBLIC_METHODS );
67
- });
68
- assertThat (this .hints .proxies ().jdkProxies ()).anySatisfy (jdkProxyHint ->
69
- assertThat (jdkProxyHint .getProxiedInterfaces ()).containsExactly (
70
- TypeReference .of (RetryInvoker .class ), TypeReference .of (SynthesizedAnnotation .class )));
89
+ };
90
+ }
91
+
92
+ private Consumer <JdkProxyHint > annotationProxy (Class <?> type ) {
93
+ return jdkProxyHint -> assertThat (jdkProxyHint .getProxiedInterfaces ())
94
+ .containsExactly (TypeReference .of (type ),
95
+ TypeReference .of (SynthesizedAnnotation .class ));
71
96
}
72
97
73
98
@@ -81,6 +106,11 @@ static class RetryInvokerClass {
81
106
82
107
}
83
108
109
+ @ RetryWithEnabledFlagInvoker
110
+ static class RetryWithEnabledFlagInvokerClass {
111
+
112
+ }
113
+
84
114
85
115
@ Target ({ ElementType .TYPE , ElementType .ANNOTATION_TYPE })
86
116
@ Retention (RetentionPolicy .RUNTIME )
@@ -102,4 +132,17 @@ static class RetryInvokerClass {
102
132
103
133
}
104
134
135
+ @ Target ({ ElementType .TYPE })
136
+ @ Retention (RetentionPolicy .RUNTIME )
137
+ @ Documented
138
+ @ RetryInvoker
139
+ @interface RetryWithEnabledFlagInvoker {
140
+
141
+ @ AliasFor (attribute = "value" , annotation = RetryInvoker .class )
142
+ int value () default 5 ;
143
+
144
+ boolean enabled () default true ;
145
+
146
+ }
147
+
105
148
}
0 commit comments