Skip to content

Commit a97ff39

Browse files
committed
Add reflection hint on Publisher for bean destroy support
Prior to this commit, `DisposableBeanAdapter` supported reactive bean destroy methods by detected if `Publisher` is available on the classpath. The AOT engine did not contribute a reflection hint for this call. This commit ensures that this reflection hint is registered in all cases, even if there are no destroy methods detected on beans. Fixes gh-31278
1 parent d46c26d commit a97ff39

File tree

2 files changed

+12
-0
lines changed

2 files changed

+12
-0
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGenerator.java

+3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.springframework.aot.generate.GeneratedMethods;
3636
import org.springframework.aot.hint.ExecutableMode;
3737
import org.springframework.aot.hint.RuntimeHints;
38+
import org.springframework.aot.hint.TypeReference;
3839
import org.springframework.beans.BeanUtils;
3940
import org.springframework.beans.MutablePropertyValues;
4041
import org.springframework.beans.PropertyValue;
@@ -128,6 +129,8 @@ CodeBlock generateCode(RootBeanDefinition beanDefinition) {
128129

129130
private void addInitDestroyMethods(Builder code, AbstractBeanDefinition beanDefinition,
130131
@Nullable String[] methodNames, String format) {
132+
// For Publisher-based destroy methods
133+
this.hints.reflection().registerType(TypeReference.of("org.reactivestreams.Publisher"));
131134
if (!ObjectUtils.isEmpty(methodNames)) {
132135
Class<?> beanType = ClassUtils.getUserClass(beanDefinition.getResolvableType().toClass());
133136
Arrays.stream(methodNames).forEach(methodName -> addInitDestroyHint(beanType, methodName));

spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGeneratorTests.java

+9
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.junit.jupiter.api.BeforeEach;
3232
import org.junit.jupiter.api.Nested;
3333
import org.junit.jupiter.api.Test;
34+
import org.reactivestreams.Publisher;
3435

3536
import org.springframework.aot.generate.GeneratedClass;
3637
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
@@ -413,27 +414,35 @@ void multipleInitMethods() {
413414
@Test
414415
void noDestroyMethod() {
415416
compile((beanDef, compiled) -> assertThat(beanDef.getDestroyMethodNames()).isNull());
417+
assertReflectionOnPublisher();
416418
}
417419

418420
@Test
419421
void singleDestroyMethod() {
420422
beanDefinition.setDestroyMethodName("destroy");
421423
compile((beanDef, compiled) -> assertThat(beanDef.getDestroyMethodNames()).containsExactly("destroy"));
422424
assertHasMethodInvokeHints(InitDestroyBean.class, "destroy");
425+
assertReflectionOnPublisher();
423426
}
424427

425428
@Test
426429
void privateDestroyMethod() {
427430
beanDefinition.setDestroyMethodName(privateDestroyMethod);
428431
compile((beanDef, compiled) -> assertThat(beanDef.getDestroyMethodNames()).containsExactly(privateDestroyMethod));
429432
assertHasMethodInvokeHints(InitDestroyBean.class, "privateDestroy");
433+
assertReflectionOnPublisher();
430434
}
431435

432436
@Test
433437
void multipleDestroyMethods() {
434438
beanDefinition.setDestroyMethodNames("destroy", privateDestroyMethod);
435439
compile((beanDef, compiled) -> assertThat(beanDef.getDestroyMethodNames()).containsExactly("destroy", privateDestroyMethod));
436440
assertHasMethodInvokeHints(InitDestroyBean.class, "destroy", "privateDestroy");
441+
assertReflectionOnPublisher();
442+
}
443+
444+
private void assertReflectionOnPublisher() {
445+
assertThat(RuntimeHintsPredicates.reflection().onType(Publisher.class)).accepts(generationContext.getRuntimeHints());
437446
}
438447

439448
}

0 commit comments

Comments
 (0)