diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfigurationTests.java index 2293c90a79..6b65831cd2 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfigurationTests.java @@ -23,7 +23,6 @@ import com.google.gson.Gson; import jakarta.json.bind.Jsonb; import org.junit.jupiter.api.Test; -import org.springframework.aot.hint.MemberCategory; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; import org.springframework.beans.factory.config.BeanDefinition; @@ -67,6 +66,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Sebastien Deleuze * @author EddĂș MelĂ©ndez * @author Moritz Halbritter + * @author Sebastien Deleuze */ class HttpMessageConvertersAutoConfigurationTests { @@ -281,9 +281,12 @@ class HttpMessageConvertersAutoConfigurationTests { void shouldRegisterHints() { RuntimeHints hints = new RuntimeHints(); new HttpMessageConvertersAutoConfigurationRuntimeHints().registerHints(hints, getClass().getClassLoader()); - assertThat(RuntimeHintsPredicates.reflection().onType(Encoding.class) - .withMemberCategories(MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INVOKE_PUBLIC_METHODS)) - .accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onType(Encoding.class)).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onMethod(Encoding.class, "getCharset")).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onMethod(Encoding.class, "setCharset")).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onMethod(Encoding.class, "isForce")).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onMethod(Encoding.class, "setForce")).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onMethod(Encoding.class, "shouldForce")).rejects(hints); } private ApplicationContextRunner allOptionsRunner() { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesReflectionHintsProcessor.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesReflectionHintsProcessor.java index a29e83cdb9..507647224f 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesReflectionHintsProcessor.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesReflectionHintsProcessor.java @@ -29,7 +29,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.ExecutableMode; import org.springframework.aot.hint.ReflectionHints; import org.springframework.beans.BeanInfoFactory; import org.springframework.beans.ExtendedBeanInfoFactory; @@ -44,6 +44,7 @@ import org.springframework.util.ReflectionUtils; * * @author Andy Wilkinson * @author Moritz Halbritter + * @author Sebastien Deleuze * @since 3.0.0 */ public final class ConfigurationPropertiesReflectionHintsProcessor { @@ -95,8 +96,6 @@ public final class ConfigurationPropertiesReflectionHintsProcessor { return; } this.seen.add(this.type); - reflectionHints.registerType(this.type, (hint) -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS, - MemberCategory.INVOKE_PUBLIC_METHODS)); handleConstructor(reflectionHints); if (this.bindConstructor != null) { handleValueObjectProperties(reflectionHints); @@ -129,14 +128,19 @@ public final class ConfigurationPropertiesReflectionHintsProcessor { private void handleJavaBeanProperties(ReflectionHints reflectionHints) { for (PropertyDescriptor propertyDescriptor : this.beanInfo.getPropertyDescriptors()) { + Method writeMethod = propertyDescriptor.getWriteMethod(); + if (writeMethod != null) { + reflectionHints.registerMethod(writeMethod, ExecutableMode.INVOKE); + } Method readMethod = propertyDescriptor.getReadMethod(); if (readMethod != null) { ResolvableType propertyType = ResolvableType.forMethodReturnType(readMethod, this.type); String propertyName = propertyDescriptor.getName(); - if (isSetterMandatory(propertyName, propertyType) && propertyDescriptor.getWriteMethod() == null) { + if (isSetterMandatory(propertyName, propertyType) && writeMethod == null) { continue; } handleProperty(reflectionHints, propertyName, propertyType); + reflectionHints.registerMethod(readMethod, ExecutableMode.INVOKE); } } } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java index 5326bddcb4..eabbf1164f 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java @@ -41,7 +41,6 @@ import org.mockito.InOrder; import org.mockito.Mockito; import reactor.core.publisher.Mono; -import org.springframework.aot.hint.MemberCategory; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; import org.springframework.beans.CachedIntrospectionResults; @@ -158,7 +157,7 @@ import static org.mockito.Mockito.spy; * @author Marten Deinum * @author Nguyen Bao Sach * @author Chris Bono - * @author Brian Clozel + * @author Sebastien Deleuze */ @ExtendWith(OutputCaptureExtension.class) class SpringApplicationTests { @@ -1309,9 +1308,12 @@ class SpringApplicationTests { void shouldRegisterHints() { RuntimeHints hints = new RuntimeHints(); new SpringApplicationRuntimeHints().registerHints(hints, getClass().getClassLoader()); - assertThat(RuntimeHintsPredicates.reflection().onType(SpringApplication.class) - .withMemberCategories(MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INVOKE_PUBLIC_METHODS)) - .accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onType(SpringApplication.class)).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onMethod(SpringApplication.class, "setBannerMode")) + .accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onMethod(SpringApplication.class, "getSources")).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onMethod(SpringApplication.class, "setSources")).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onMethod(SpringApplication.class, "load")).rejects(hints); } private ArgumentMatcher isAvailabilityChangeEventWithState( diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests.java index 4bb0d996c3..a3b1653db9 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests.java @@ -31,7 +31,6 @@ import org.springframework.aot.generate.DefaultGenerationContext; import org.springframework.aot.generate.GenerationContext; import org.springframework.aot.generate.InMemoryGeneratedFiles; import org.springframework.aot.hint.ExecutableHint; -import org.springframework.aot.hint.MemberCategory; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.TypeHint; import org.springframework.aot.hint.TypeReference; @@ -57,6 +56,7 @@ import static org.mockito.Mockito.mock; * * @author Stephane Nicoll * @author Moritz Halbritter + * @author Sebastien Deleuze */ class ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests { @@ -233,26 +233,17 @@ class ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests { @Test void processConfigurationPropertiesWithNestedGenerics() { RuntimeHints runtimeHints = process(NestedGenerics.class); - assertThat(RuntimeHintsPredicates.reflection().onType(NestedGenerics.class) - .withMemberCategories(MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INVOKE_PUBLIC_METHODS)) - .accepts(runtimeHints); - assertThat(RuntimeHintsPredicates.reflection().onType(NestedGenerics.Nested.class) - .withMemberCategories(MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INVOKE_PUBLIC_METHODS)) - .accepts(runtimeHints); + assertThat(RuntimeHintsPredicates.reflection().onType(NestedGenerics.class)).accepts(runtimeHints); + assertThat(RuntimeHintsPredicates.reflection().onType(NestedGenerics.Nested.class)).accepts(runtimeHints); } @Test void processConfigurationPropertiesWithMultipleNestedClasses() { RuntimeHints runtimeHints = process(TripleNested.class); - assertThat(RuntimeHintsPredicates.reflection().onType(TripleNested.class) - .withMemberCategories(MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INVOKE_PUBLIC_METHODS)) - .accepts(runtimeHints); - assertThat(RuntimeHintsPredicates.reflection().onType(TripleNested.DoubleNested.class) - .withMemberCategories(MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INVOKE_PUBLIC_METHODS)) - .accepts(runtimeHints); - assertThat(RuntimeHintsPredicates.reflection().onType(TripleNested.DoubleNested.Nested.class) - .withMemberCategories(MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INVOKE_PUBLIC_METHODS)) - .accepts(runtimeHints); + assertThat(RuntimeHintsPredicates.reflection().onType(TripleNested.class)).accepts(runtimeHints); + assertThat(RuntimeHintsPredicates.reflection().onType(TripleNested.DoubleNested.class)).accepts(runtimeHints); + assertThat(RuntimeHintsPredicates.reflection().onType(TripleNested.DoubleNested.Nested.class)) + .accepts(runtimeHints); } private Consumer javaBeanBinding(Class type) { @@ -263,8 +254,9 @@ class ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests { return (entry) -> { assertThat(entry.getType()).isEqualTo(TypeReference.of(type)); assertThat(entry.constructors()).singleElement().satisfies(match(constructor)); - assertThat(entry.getMemberCategories()).containsOnly(MemberCategory.INVOKE_DECLARED_METHODS, - MemberCategory.INVOKE_PUBLIC_METHODS); + assertThat(entry.getMemberCategories()).isEmpty(); + assertThat(entry.methods()).allMatch((t) -> t.getName().startsWith("set") || t.getName().startsWith("get") + || t.getName().startsWith("is")); }; } @@ -272,8 +264,8 @@ class ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests { return (entry) -> { assertThat(entry.getType()).isEqualTo(TypeReference.of(type)); assertThat(entry.constructors()).singleElement().satisfies(match(constructor)); - assertThat(entry.getMemberCategories()).containsOnly(MemberCategory.INVOKE_DECLARED_METHODS, - MemberCategory.INVOKE_PUBLIC_METHODS); + assertThat(entry.getMemberCategories()).isEmpty(); + assertThat(entry.methods()).isEmpty(); }; }