Browse Source

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
pull/31282/head
Brian Clozel 2 years ago
parent
commit
a97ff39088
  1. 3
      spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGenerator.java
  2. 9
      spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGeneratorTests.java

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

@ -35,6 +35,7 @@ import java.util.function.Predicate; @@ -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 { @@ -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));

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

@ -31,6 +31,7 @@ import javax.lang.model.element.Modifier; @@ -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 { @@ -413,6 +414,7 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
@Test
void noDestroyMethod() {
compile((beanDef, compiled) -> assertThat(beanDef.getDestroyMethodNames()).isNull());
assertReflectionOnPublisher();
}
@Test
@ -420,6 +422,7 @@ class BeanDefinitionPropertiesCodeGeneratorTests { @@ -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 { @@ -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 { @@ -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());
}
}

Loading…
Cancel
Save