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
This commit is contained in:
		
							parent
							
								
									d46c26d903
								
							
						
					
					
						commit
						a97ff39088
					
				|  | @ -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)); | ||||
|  |  | |||
|  | @ -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()); | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue