Polish reflection hints on bean registration interfaces

This commit ensures that we register reflection hints on interfaces in
the entire type hierarchy.

Closes gh-31350
This commit is contained in:
Brian Clozel 2023-10-03 11:24:47 +02:00
parent b832df6087
commit 1fd54912d2
2 changed files with 17 additions and 10 deletions

View File

@ -36,6 +36,7 @@ import org.springframework.core.ResolvableType;
import org.springframework.javapoet.ClassName; import org.springframework.javapoet.ClassName;
import org.springframework.javapoet.CodeBlock; import org.springframework.javapoet.CodeBlock;
import org.springframework.javapoet.MethodSpec; import org.springframework.javapoet.MethodSpec;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
/** /**
@ -118,8 +119,14 @@ class BeanRegistrationsAotContribution
ReflectionHints hints = runtimeHints.reflection(); ReflectionHints hints = runtimeHints.reflection();
Class<?> beanClass = beanRegistrationKey.beanClass(); Class<?> beanClass = beanRegistrationKey.beanClass();
hints.registerType(beanClass, MemberCategory.INTROSPECT_PUBLIC_METHODS, MemberCategory.INTROSPECT_DECLARED_METHODS); hints.registerType(beanClass, MemberCategory.INTROSPECT_PUBLIC_METHODS, MemberCategory.INTROSPECT_DECLARED_METHODS);
for (Class<?> interfaceType : beanClass.getInterfaces()) { Class<?> currentClass = beanClass;
hints.registerType(interfaceType, MemberCategory.INTROSPECT_PUBLIC_METHODS); while (currentClass != null && currentClass != Object.class) {
for (Class<?> interfaceType : currentClass.getInterfaces()) {
if (!ClassUtils.isJavaLanguageInterface(interfaceType)) {
hints.registerType(interfaceType, MemberCategory.INTROSPECT_PUBLIC_METHODS);
}
}
currentClass = currentClass.getSuperclass();
} }
// Workaround for https://github.com/oracle/graal/issues/6510 // Workaround for https://github.com/oracle/graal/issues/6510
if (beanClass.isRecord()) { if (beanClass.isRecord()) {

View File

@ -36,7 +36,9 @@ import org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.Re
import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RegisteredBean; import org.springframework.beans.factory.support.RegisteredBean;
import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.testfixture.beans.Employee;
import org.springframework.beans.testfixture.beans.GenericBeanWithBounds; import org.springframework.beans.testfixture.beans.GenericBeanWithBounds;
import org.springframework.beans.testfixture.beans.ITestBean;
import org.springframework.beans.testfixture.beans.Person; import org.springframework.beans.testfixture.beans.Person;
import org.springframework.beans.testfixture.beans.RecordBean; import org.springframework.beans.testfixture.beans.RecordBean;
import org.springframework.beans.testfixture.beans.TestBean; import org.springframework.beans.testfixture.beans.TestBean;
@ -141,19 +143,17 @@ class BeanRegistrationsAotContributionTests {
@Test @Test
void applyToRegisterReflectionHints() { void applyToRegisterReflectionHints() {
RegisteredBean registeredBean = registerBean(new RootBeanDefinition(TestBean.class)); RegisteredBean registeredBean = registerBean(new RootBeanDefinition(Employee.class));
BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator(this.methodGeneratorFactory, BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator(this.methodGeneratorFactory,
registeredBean, null, List.of()); registeredBean, null, List.of());
BeanRegistrationsAotContribution contribution = createContribution(TestBean.class, generator); BeanRegistrationsAotContribution contribution = createContribution(Employee.class, generator);
contribution.applyTo(this.generationContext, this.beanFactoryInitializationCode); contribution.applyTo(this.generationContext, this.beanFactoryInitializationCode);
assertThat(reflection().onType(TestBean.class) assertThat(reflection().onType(Employee.class)
.withMemberCategories(MemberCategory.INTROSPECT_PUBLIC_METHODS, MemberCategory.INTROSPECT_DECLARED_METHODS)) .withMemberCategories(MemberCategory.INTROSPECT_PUBLIC_METHODS, MemberCategory.INTROSPECT_DECLARED_METHODS))
.accepts(this.generationContext.getRuntimeHints()); .accepts(this.generationContext.getRuntimeHints());
for (Class<?> interfaceType : TestBean.class.getInterfaces()) { assertThat(reflection().onType(ITestBean.class)
assertThat(reflection().onType(interfaceType) .withMemberCategory(MemberCategory.INTROSPECT_PUBLIC_METHODS))
.withMemberCategory(MemberCategory.INTROSPECT_PUBLIC_METHODS)) .accepts(this.generationContext.getRuntimeHints());
.accepts(this.generationContext.getRuntimeHints());
}
} }
@Test @Test