50
50
* {@link BeanRegistrationAotContribution#customizeBeanRegistrationCodeFragments(GenerationContext, BeanRegistrationCodeFragments)}.
51
51
* The generated code resolves potential factory methods accepting either a {@link ManagedTypes} instance, or a
52
52
* {@link List} of either {@link Class} or {@link String} (classname) values.
53
- *
54
- * <pre>
55
- * <code>
53
+ *
54
+ * <pre class="code">
56
55
* public static InstanceSupplier<ManagedTypes> instance() {
57
56
* return (registeredBean) -> {
58
57
* var types = List.of("com.example.A", "com.example.B");
59
58
* return ManagedTypes.ofStream(types.stream().map(it -> ClassUtils.forName(it, registeredBean.getBeanFactory().getBeanClassLoader())));
60
59
* }
61
60
* }
62
- * </code>
63
61
* </pre>
64
62
*
65
63
* @author John Blum
66
64
* @author Christoph Strobl
65
+ * @author Mark Paluch
67
66
* @see org.springframework.beans.factory.aot.BeanRegistrationAotContribution
68
- * @since 3.0.0
67
+ * @since 3.0
69
68
*/
70
- public class ManagedTypesRegistrationAotContribution implements RegisteredBeanAotContribution {
69
+ class ManagedTypesRegistrationAotContribution implements RegisteredBeanAotContribution {
71
70
72
- private final AotContext aotContext ;
73
71
private final ManagedTypes managedTypes ;
72
+ private final Lazy <List <Class <?>>> sourceTypes ;
74
73
private final BiConsumer <ResolvableType , GenerationContext > contributionAction ;
75
74
private final RegisteredBean source ;
76
75
77
- public ManagedTypesRegistrationAotContribution (AotContext aotContext , @ Nullable ManagedTypes managedTypes ,
78
- RegisteredBean registeredBean , BiConsumer <ResolvableType , GenerationContext > contributionAction ) {
76
+ public ManagedTypesRegistrationAotContribution (ManagedTypes managedTypes , RegisteredBean registeredBean ,
77
+ BiConsumer <ResolvableType , GenerationContext > contributionAction ) {
79
78
80
- this .aotContext = aotContext ;
81
79
this .managedTypes = managedTypes ;
80
+ this .sourceTypes = Lazy .of (managedTypes ::toList );
82
81
this .contributionAction = contributionAction ;
83
82
this .source = registeredBean ;
84
83
}
85
84
86
- protected AotContext getAotContext () {
87
- return this .aotContext ;
88
- }
89
-
90
- protected ManagedTypes getManagedTypes () {
91
- return managedTypes == null ? ManagedTypes .empty () : managedTypes ;
92
- }
93
-
94
85
@ Override
95
86
public void applyTo (GenerationContext generationContext , BeanRegistrationCode beanRegistrationCode ) {
96
87
97
- List <Class <?>> types = getManagedTypes (). toList ();
88
+ List <Class <?>> types = sourceTypes . get ();
98
89
99
90
if (!types .isEmpty ()) {
100
91
TypeCollector .inspect (types ).forEach (type -> contributionAction .accept (type , generationContext ));
@@ -109,7 +100,7 @@ public BeanRegistrationCodeFragments customizeBeanRegistrationCodeFragments(Gene
109
100
return codeFragments ;
110
101
}
111
102
112
- ManagedTypesInstanceCodeFragment fragment = new ManagedTypesInstanceCodeFragment (getManagedTypes (), source ,
103
+ ManagedTypesInstanceCodeFragment fragment = new ManagedTypesInstanceCodeFragment (sourceTypes . get (), source ,
113
104
codeFragments );
114
105
return fragment .canGenerateCode () ? fragment : codeFragments ;
115
106
}
@@ -119,32 +110,27 @@ public RegisteredBean getSource() {
119
110
return source ;
120
111
}
121
112
113
+ /**
114
+ * Class used to generate the fragment of code needed to define a {@link ManagedTypes} bean from previously discovered
115
+ * managed types.
116
+ */
122
117
static class ManagedTypesInstanceCodeFragment extends BeanRegistrationCodeFragments {
123
118
124
- private ManagedTypes sourceTypes ;
125
- private RegisteredBean source ;
126
- private Lazy <Method > instanceMethod = Lazy .of (this ::findInstanceFactory );
119
+ public static final ResolvableType LIST_TYPE = ResolvableType .forType (List .class );
120
+ public static final ResolvableType MANAGED_TYPES_TYPE = ResolvableType .forType (ManagedTypes .class );
121
+ private final List <Class <?>> sourceTypes ;
122
+ private final RegisteredBean source ;
123
+ private final Lazy <Method > instanceMethod = Lazy .of (this ::findInstanceFactory );
127
124
128
- protected ManagedTypesInstanceCodeFragment (ManagedTypes managedTypes , RegisteredBean source ,
125
+ protected ManagedTypesInstanceCodeFragment (List < Class <?>> sourceTypes , RegisteredBean source ,
129
126
BeanRegistrationCodeFragments codeFragments ) {
130
127
131
128
super (codeFragments );
132
129
133
- this .sourceTypes = managedTypes ;
130
+ this .sourceTypes = sourceTypes ;
134
131
this .source = source ;
135
132
}
136
133
137
- /**
138
- * @return {@literal true} if the instance method code can be generated. {@literal false} otherwise.
139
- */
140
- boolean canGenerateCode () {
141
-
142
- if (ObjectUtils .nullSafeEquals (source .getBeanClass (), ManagedTypes .class )) {
143
- return true ;
144
- }
145
- return instanceMethod .getNullable () != null ;
146
- }
147
-
148
134
@ Override
149
135
public CodeBlock generateInstanceSupplierCode (GenerationContext generationContext ,
150
136
BeanRegistrationCode beanRegistrationCode , Executable constructorOrFactoryMethod ,
@@ -156,33 +142,20 @@ public CodeBlock generateInstanceSupplierCode(GenerationContext generationContex
156
142
return CodeBlock .of ("$T.$L()" , beanRegistrationCode .getClassName (), generatedMethod .getName ());
157
143
}
158
144
159
- private CodeBlock toCodeBlock (List <Class <?>> values , boolean allPublic ) {
145
+ /**
146
+ * @return {@literal true} if the instance method code can be generated. {@literal false} otherwise.
147
+ */
148
+ boolean canGenerateCode () {
160
149
161
- if (allPublic ) {
162
- return CodeBlock . join ( values . stream (). map ( value -> CodeBlock . of ( "$T.class" , value )). toList (), ", " ) ;
150
+ if (ObjectUtils . nullSafeEquals ( source . getBeanClass (), ManagedTypes . class ) ) {
151
+ return true ;
163
152
}
164
- return CodeBlock .join (values .stream ().map (value -> CodeBlock .of ("$S" , value .getName ())).toList (), ", " );
165
- }
166
-
167
- private Method findInstanceFactory () {
168
-
169
- for (Method beanMethod : ReflectionUtils .getDeclaredMethods (source .getBeanClass ())) {
170
153
171
- if (beanMethod .getParameterCount () == 1 && java .lang .reflect .Modifier .isPublic (beanMethod .getModifiers ())
172
- && java .lang .reflect .Modifier .isStatic (beanMethod .getModifiers ())) {
173
- ResolvableType parameterType = ResolvableType .forMethodParameter (beanMethod , 0 , source .getBeanClass ());
174
- if (parameterType .isAssignableFrom (ResolvableType .forType (List .class ))
175
- || parameterType .isAssignableFrom (ResolvableType .forType (ManagedTypes .class ))) {
176
- return beanMethod ;
177
- }
178
- }
179
- }
180
- return null ;
154
+ return instanceMethod .getNullable () != null ;
181
155
}
182
156
183
157
void generateInstanceFactory (Builder method ) {
184
158
185
- List <Class <?>> sourceTypes = this .sourceTypes .toList ();
186
159
boolean allSourceTypesVisible = sourceTypes .stream ()
187
160
.allMatch (it -> AccessVisibility .PUBLIC .equals (AccessVisibility .forClass (it )));
188
161
@@ -207,6 +180,7 @@ void generateInstanceFactory(Builder method) {
207
180
.addStatement ("throw new $T($S, e)" , IllegalArgumentException .class , "Cannot to load type" ).endControlFlow ()
208
181
.endControlFlow ("))" ).build ());
209
182
}
183
+
210
184
if (ObjectUtils .nullSafeEquals (source .getBeanClass (), ManagedTypes .class )) {
211
185
builder .add ("return managedTypes" );
212
186
} else {
@@ -221,8 +195,42 @@ void generateInstanceFactory(Builder method) {
221
195
instanceFactoryMethod .getName (), "managedTypes" );
222
196
}
223
197
}
198
+
224
199
builder .endControlFlow (")" );
225
200
method .addCode (builder .build ());
226
201
}
202
+
203
+ private CodeBlock toCodeBlock (List <Class <?>> values , boolean allPublic ) {
204
+
205
+ if (allPublic ) {
206
+ return CodeBlock .join (values .stream ().map (value -> CodeBlock .of ("$T.class" , value )).toList (), ", " );
207
+ }
208
+ return CodeBlock .join (values .stream ().map (value -> CodeBlock .of ("$S" , value .getName ())).toList (), ", " );
209
+ }
210
+
211
+ @ Nullable
212
+ private Method findInstanceFactory () {
213
+
214
+ for (Method beanMethod : ReflectionUtils .getDeclaredMethods (source .getBeanClass ())) {
215
+
216
+ if (!isInstanceFactory (beanMethod )) {
217
+ continue ;
218
+ }
219
+
220
+ ResolvableType parameterType = ResolvableType .forMethodParameter (beanMethod , 0 , source .getBeanClass ());
221
+
222
+ if (parameterType .isAssignableFrom (LIST_TYPE ) || parameterType .isAssignableFrom (MANAGED_TYPES_TYPE )) {
223
+ return beanMethod ;
224
+ }
225
+ }
226
+
227
+ return null ;
228
+ }
229
+
230
+ private static boolean isInstanceFactory (Method beanMethod ) {
231
+ return beanMethod .getParameterCount () == 1 //
232
+ && java .lang .reflect .Modifier .isPublic (beanMethod .getModifiers ()) //
233
+ && java .lang .reflect .Modifier .isStatic (beanMethod .getModifiers ());
234
+ }
227
235
}
228
236
}
0 commit comments