From e749cd1ef1abda77d6e185dd22bee12258868b78 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Thu, 20 Oct 2022 12:10:21 +0200 Subject: [PATCH] Add constructor introspection hint on Configuration class target See gh-29358 --- .../ConfigurationClassPostProcessor.java | 14 +++++++++----- .../aot/ApplicationContextAotGeneratorTests.java | 11 +++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java index 7cdd6f1db14..6c06e366c2b 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java @@ -39,7 +39,9 @@ import org.apache.commons.logging.LogFactory; import org.springframework.aop.framework.autoproxy.AutoProxyUtils; import org.springframework.aot.generate.GeneratedMethod; import org.springframework.aot.generate.GenerationContext; +import org.springframework.aot.hint.ExecutableMode; import org.springframework.aot.hint.ResourceHints; +import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.TypeReference; import org.springframework.beans.PropertyValues; import org.springframework.beans.factory.BeanClassLoaderAware; @@ -739,20 +741,22 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo public CodeBlock generateInstanceSupplierCode(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, Executable constructorOrFactoryMethod, boolean allowDirectSupplierShortcut) { + Executable executableToUse = proxyExecutable(generationContext.getRuntimeHints(), constructorOrFactoryMethod); return super.generateInstanceSupplierCode(generationContext, beanRegistrationCode, - proxyExecutable(constructorOrFactoryMethod), allowDirectSupplierShortcut); + executableToUse, allowDirectSupplierShortcut); } - private Executable proxyExecutable(Executable rawClassExecutable) { - if (rawClassExecutable instanceof Constructor) { + private Executable proxyExecutable(RuntimeHints runtimeHints, Executable userExecutable) { + if (userExecutable instanceof Constructor userConstructor) { try { - return this.proxyClass.getConstructor(rawClassExecutable.getParameterTypes()); + runtimeHints.reflection().registerConstructor(userConstructor, ExecutableMode.INTROSPECT); + return this.proxyClass.getConstructor(userExecutable.getParameterTypes()); } catch (NoSuchMethodException ex) { throw new IllegalStateException("No matching constructor found on proxy " + this.proxyClass, ex); } } - return rawClassExecutable; + return userExecutable; } } diff --git a/spring-context/src/test/java/org/springframework/context/aot/ApplicationContextAotGeneratorTests.java b/spring-context/src/test/java/org/springframework/context/aot/ApplicationContextAotGeneratorTests.java index 10d6479c1a1..bdf218c04e8 100644 --- a/spring-context/src/test/java/org/springframework/context/aot/ApplicationContextAotGeneratorTests.java +++ b/spring-context/src/test/java/org/springframework/context/aot/ApplicationContextAotGeneratorTests.java @@ -17,6 +17,7 @@ package org.springframework.context.aot; import java.io.IOException; +import java.lang.reflect.Constructor; import java.lang.reflect.Proxy; import java.util.List; import java.util.function.BiConsumer; @@ -333,6 +334,16 @@ class ApplicationContextAotGeneratorTests { }); } + @Test + void processAheadOfTimeWhenHasCglibProxyWithArgumentsRegisterIntrospectionHintsOnUserClass() { + GenericApplicationContext applicationContext = new AnnotationConfigApplicationContext(); + applicationContext.registerBean(ConfigurableCglibConfiguration.class); + TestGenerationContext generationContext = processAheadOfTime(applicationContext); + Constructor userConstructor = ConfigurableCglibConfiguration.class.getDeclaredConstructors()[0]; + assertThat(RuntimeHintsPredicates.reflection().onConstructor(userConstructor).introspect()) + .accepts(generationContext.getRuntimeHints()); + } + } private Consumer> doesNotHaveProxyFor(Class target) {