5050 * {@link BeanRegistrationAotContribution#customizeBeanRegistrationCodeFragments(GenerationContext, BeanRegistrationCodeFragments)}.
5151 * The generated code resolves potential factory methods accepting either a {@link ManagedTypes} instance, or a
5252 * {@link List} of either {@link Class} or {@link String} (classname) values.
53- *
54- * <pre>
55- * <code>
53+ *
54+ * <pre class="code">
5655 * public static InstanceSupplier<ManagedTypes> instance() {
5756 * return (registeredBean) -> {
5857 * var types = List.of("com.example.A", "com.example.B");
5958 * return ManagedTypes.ofStream(types.stream().map(it -> ClassUtils.forName(it, registeredBean.getBeanFactory().getBeanClassLoader())));
6059 * }
6160 * }
62- * </code>
6361 * </pre>
6462 *
6563 * @author John Blum
6664 * @author Christoph Strobl
65+ * @author Mark Paluch
6766 * @see org.springframework.beans.factory.aot.BeanRegistrationAotContribution
68- * @since 3.0.0
67+ * @since 3.0
6968 */
70- public class ManagedTypesRegistrationAotContribution implements RegisteredBeanAotContribution {
69+ class ManagedTypesRegistrationAotContribution implements RegisteredBeanAotContribution {
7170
72- private final AotContext aotContext ;
7371 private final ManagedTypes managedTypes ;
72+ private final Lazy <List <Class <?>>> sourceTypes ;
7473 private final BiConsumer <ResolvableType , GenerationContext > contributionAction ;
7574 private final RegisteredBean source ;
7675
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 ) {
7978
80- this .aotContext = aotContext ;
8179 this .managedTypes = managedTypes ;
80+ this .sourceTypes = Lazy .of (managedTypes ::toList );
8281 this .contributionAction = contributionAction ;
8382 this .source = registeredBean ;
8483 }
8584
86- protected AotContext getAotContext () {
87- return this .aotContext ;
88- }
89-
90- protected ManagedTypes getManagedTypes () {
91- return managedTypes == null ? ManagedTypes .empty () : managedTypes ;
92- }
93-
9485 @ Override
9586 public void applyTo (GenerationContext generationContext , BeanRegistrationCode beanRegistrationCode ) {
9687
97- List <Class <?>> types = getManagedTypes (). toList ();
88+ List <Class <?>> types = sourceTypes . get ();
9889
9990 if (!types .isEmpty ()) {
10091 TypeCollector .inspect (types ).forEach (type -> contributionAction .accept (type , generationContext ));
@@ -109,7 +100,7 @@ public BeanRegistrationCodeFragments customizeBeanRegistrationCodeFragments(Gene
109100 return codeFragments ;
110101 }
111102
112- ManagedTypesInstanceCodeFragment fragment = new ManagedTypesInstanceCodeFragment (getManagedTypes (), source ,
103+ ManagedTypesInstanceCodeFragment fragment = new ManagedTypesInstanceCodeFragment (sourceTypes . get (), source ,
113104 codeFragments );
114105 return fragment .canGenerateCode () ? fragment : codeFragments ;
115106 }
@@ -119,32 +110,27 @@ public RegisteredBean getSource() {
119110 return source ;
120111 }
121112
113+ /**
114+ * Class used to generate the fragment of code needed to define a {@link ManagedTypes} bean from previously discovered
115+ * managed types.
116+ */
122117 static class ManagedTypesInstanceCodeFragment extends BeanRegistrationCodeFragments {
123118
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 );
127124
128- protected ManagedTypesInstanceCodeFragment (ManagedTypes managedTypes , RegisteredBean source ,
125+ protected ManagedTypesInstanceCodeFragment (List < Class <?>> sourceTypes , RegisteredBean source ,
129126 BeanRegistrationCodeFragments codeFragments ) {
130127
131128 super (codeFragments );
132129
133- this .sourceTypes = managedTypes ;
130+ this .sourceTypes = sourceTypes ;
134131 this .source = source ;
135132 }
136133
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-
148134 @ Override
149135 public CodeBlock generateInstanceSupplierCode (GenerationContext generationContext ,
150136 BeanRegistrationCode beanRegistrationCode , Executable constructorOrFactoryMethod ,
@@ -156,33 +142,20 @@ public CodeBlock generateInstanceSupplierCode(GenerationContext generationContex
156142 return CodeBlock .of ("$T.$L()" , beanRegistrationCode .getClassName (), generatedMethod .getName ());
157143 }
158144
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 () {
160149
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 ;
163152 }
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 ())) {
170153
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 ;
181155 }
182156
183157 void generateInstanceFactory (Builder method ) {
184158
185- List <Class <?>> sourceTypes = this .sourceTypes .toList ();
186159 boolean allSourceTypesVisible = sourceTypes .stream ()
187160 .allMatch (it -> AccessVisibility .PUBLIC .equals (AccessVisibility .forClass (it )));
188161
@@ -207,6 +180,7 @@ void generateInstanceFactory(Builder method) {
207180 .addStatement ("throw new $T($S, e)" , IllegalArgumentException .class , "Cannot to load type" ).endControlFlow ()
208181 .endControlFlow ("))" ).build ());
209182 }
183+
210184 if (ObjectUtils .nullSafeEquals (source .getBeanClass (), ManagedTypes .class )) {
211185 builder .add ("return managedTypes" );
212186 } else {
@@ -221,8 +195,42 @@ void generateInstanceFactory(Builder method) {
221195 instanceFactoryMethod .getName (), "managedTypes" );
222196 }
223197 }
198+
224199 builder .endControlFlow (")" );
225200 method .addCode (builder .build ());
226201 }
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+ }
227235 }
228236}
0 commit comments