diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGenerator.java b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGenerator.java index cd812f3da33..614cc32abf0 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGenerator.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGenerator.java @@ -35,6 +35,7 @@ import java.util.function.Predicate; import org.springframework.aot.generate.GeneratedMethods; import org.springframework.aot.hint.ExecutableMode; import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.TypeReference; import org.springframework.beans.BeanUtils; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.PropertyValue; @@ -128,6 +129,8 @@ class BeanDefinitionPropertiesCodeGenerator { private void addInitDestroyMethods(Builder code, AbstractBeanDefinition beanDefinition, @Nullable String[] methodNames, String format) { + // For Publisher-based destroy methods + this.hints.reflection().registerType(TypeReference.of("org.reactivestreams.Publisher")); if (!ObjectUtils.isEmpty(methodNames)) { Class beanType = ClassUtils.getUserClass(beanDefinition.getResolvableType().toClass()); Arrays.stream(methodNames).forEach(methodName -> addInitDestroyHint(beanType, methodName)); diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGeneratorTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGeneratorTests.java index 3edeb086c2b..aa1f663b8b2 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGeneratorTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGeneratorTests.java @@ -31,6 +31,7 @@ import javax.lang.model.element.Modifier; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.reactivestreams.Publisher; import org.springframework.aot.generate.GeneratedClass; import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; @@ -413,6 +414,7 @@ class BeanDefinitionPropertiesCodeGeneratorTests { @Test void noDestroyMethod() { compile((beanDef, compiled) -> assertThat(beanDef.getDestroyMethodNames()).isNull()); + assertReflectionOnPublisher(); } @Test @@ -420,6 +422,7 @@ class BeanDefinitionPropertiesCodeGeneratorTests { beanDefinition.setDestroyMethodName("destroy"); compile((beanDef, compiled) -> assertThat(beanDef.getDestroyMethodNames()).containsExactly("destroy")); assertHasMethodInvokeHints(InitDestroyBean.class, "destroy"); + assertReflectionOnPublisher(); } @Test @@ -427,6 +430,7 @@ class BeanDefinitionPropertiesCodeGeneratorTests { beanDefinition.setDestroyMethodName(privateDestroyMethod); compile((beanDef, compiled) -> assertThat(beanDef.getDestroyMethodNames()).containsExactly(privateDestroyMethod)); assertHasMethodInvokeHints(InitDestroyBean.class, "privateDestroy"); + assertReflectionOnPublisher(); } @Test @@ -434,6 +438,11 @@ class BeanDefinitionPropertiesCodeGeneratorTests { beanDefinition.setDestroyMethodNames("destroy", privateDestroyMethod); compile((beanDef, compiled) -> assertThat(beanDef.getDestroyMethodNames()).containsExactly("destroy", privateDestroyMethod)); assertHasMethodInvokeHints(InitDestroyBean.class, "destroy", "privateDestroy"); + assertReflectionOnPublisher(); + } + + private void assertReflectionOnPublisher() { + assertThat(RuntimeHintsPredicates.reflection().onType(Publisher.class)).accepts(generationContext.getRuntimeHints()); } }