From d28c0396c9a2b7bc2d88006f265e701a99a0f52a Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Mon, 13 Jan 2025 15:34:34 +0100 Subject: [PATCH] Update runtime hints predicates after GraalVM changes As of gh-33847, method and field introspection is included by default when a type is registered for reflection. Many methods in ReflectionHintsPredicates are now mostly useless as their default behavior checks for introspection. This commit deprecates those methods and promotes instead invocation variants. During the upgrade, developers should replace it for an `onType` check if only reflection is required. If they were checking for invocation, they should use the new 'onXInvocation` method. Closes gh-34239 --- ...actoryInitializationAotProcessorTests.java | 4 +- ...nBeanRegistrationAotContributionTests.java | 14 +- ...efinitionPropertiesCodeGeneratorTests.java | 4 +- ...nBeanRegistrationAotContributionTests.java | 16 +-- .../ApplicationContextAotGeneratorTests.java | 6 +- ...actoryInitializationAotProcessorTests.java | 7 +- .../aot/agent/InstrumentedMethod.java | 13 +- .../predicate/ReflectionHintsPredicates.java | 122 +++++++++++++++++- .../BindingReflectionHintsRegistrarTests.java | 12 +- .../ReflectiveRuntimeHintsRegistrarTests.java | 4 +- ...terReflectionForBindingProcessorTests.java | 8 +- .../ReflectionHintsPredicatesTests.java | 95 ++------------ ...ectToObjectConverterRuntimeHintsTests.java | 8 +- ...dingReflectionHintsRegistrarKotlinTests.kt | 14 +- ...eddedDatabaseFactoryRuntimeHintsTests.java | 4 +- ...essageMappingReflectiveProcessorTests.java | 6 +- ...ocketExchangeReflectiveProcessorTests.java | 20 +-- .../jpa/EntityManagerRuntimeHintsTests.java | 6 +- ...ypesBeanRegistrationAotProcessorTests.java | 4 +- .../support/InjectionCodeGeneratorTests.java | 6 +- .../aot/DeclarativeRuntimeHintsTests.java | 4 +- ...stContextAotGeneratorIntegrationTests.java | 4 +- .../json/ProblemDetailRuntimeHintsTests.java | 6 +- .../HttpExchangeReflectiveProcessorTests.java | 14 +- 24 files changed, 224 insertions(+), 177 deletions(-) diff --git a/spring-aop/src/test/java/org/springframework/aop/aspectj/annotation/AspectJBeanFactoryInitializationAotProcessorTests.java b/spring-aop/src/test/java/org/springframework/aop/aspectj/annotation/AspectJBeanFactoryInitializationAotProcessorTests.java index a9bc36d97d52..6ab88d29fb33 100644 --- a/spring-aop/src/test/java/org/springframework/aop/aspectj/annotation/AspectJBeanFactoryInitializationAotProcessorTests.java +++ b/spring-aop/src/test/java/org/springframework/aop/aspectj/annotation/AspectJBeanFactoryInitializationAotProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,7 +50,7 @@ void shouldSkipEmptyClass() { @Test void shouldProcessAspect() { process(TestAspect.class); - assertThat(RuntimeHintsPredicates.reflection().onMethod(TestAspect.class, "alterReturnValue").invoke()) + assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(TestAspect.class, "alterReturnValue")) .accepts(this.generationContext.getRuntimeHints()); } diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanRegistrationAotContributionTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanRegistrationAotContributionTests.java index 0e38a02da29c..017074e50240 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanRegistrationAotContributionTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanRegistrationAotContributionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -94,7 +94,7 @@ void contributeWhenPrivateFieldInjectionInjectsUsingReflection() { RegisteredBean registeredBean = getAndApplyContribution( PrivateFieldInjectionSample.class); assertThat(RuntimeHintsPredicates.reflection() - .onField(PrivateFieldInjectionSample.class, "environment")) + .onType(PrivateFieldInjectionSample.class)) .accepts(this.generationContext.getRuntimeHints()); compile(registeredBean, (postProcessor, compiled) -> { PrivateFieldInjectionSample instance = new PrivateFieldInjectionSample(); @@ -113,7 +113,7 @@ void contributeWhenPackagePrivateFieldInjectionInjectsUsingConsumer() { RegisteredBean registeredBean = getAndApplyContribution( PackagePrivateFieldInjectionSample.class); assertThat(RuntimeHintsPredicates.reflection() - .onField(PackagePrivateFieldInjectionSample.class, "environment")) + .onType(PackagePrivateFieldInjectionSample.class)) .accepts(this.generationContext.getRuntimeHints()); compile(registeredBean, (postProcessor, compiled) -> { PackagePrivateFieldInjectionSample instance = new PackagePrivateFieldInjectionSample(); @@ -132,7 +132,7 @@ void contributeWhenPackagePrivateFieldInjectionOnParentClassInjectsUsingReflecti RegisteredBean registeredBean = getAndApplyContribution( PackagePrivateFieldInjectionFromParentSample.class); assertThat(RuntimeHintsPredicates.reflection() - .onField(PackagePrivateFieldInjectionSample.class, "environment")) + .onType(PackagePrivateFieldInjectionSample.class)) .accepts(this.generationContext.getRuntimeHints()); compile(registeredBean, (postProcessor, compiled) -> { PackagePrivateFieldInjectionFromParentSample instance = new PackagePrivateFieldInjectionFromParentSample(); @@ -150,7 +150,7 @@ void contributeWhenPrivateMethodInjectionInjectsUsingReflection() { RegisteredBean registeredBean = getAndApplyContribution( PrivateMethodInjectionSample.class); assertThat(RuntimeHintsPredicates.reflection() - .onMethod(PrivateMethodInjectionSample.class, "setTestBean").invoke()) + .onMethodInvocation(PrivateMethodInjectionSample.class, "setTestBean")) .accepts(this.generationContext.getRuntimeHints()); compile(registeredBean, (postProcessor, compiled) -> { PrivateMethodInjectionSample instance = new PrivateMethodInjectionSample(); @@ -169,7 +169,7 @@ void contributeWhenPackagePrivateMethodInjectionInjectsUsingConsumer() { RegisteredBean registeredBean = getAndApplyContribution( PackagePrivateMethodInjectionSample.class); assertThat(RuntimeHintsPredicates.reflection() - .onMethod(PackagePrivateMethodInjectionSample.class, "setTestBean").introspect()) + .onType(PackagePrivateMethodInjectionSample.class)) .accepts(this.generationContext.getRuntimeHints()); compile(registeredBean, (postProcessor, compiled) -> { PackagePrivateMethodInjectionSample instance = new PackagePrivateMethodInjectionSample(); @@ -188,7 +188,7 @@ void contributeWhenPackagePrivateMethodInjectionOnParentClassInjectsUsingReflect RegisteredBean registeredBean = getAndApplyContribution( PackagePrivateMethodInjectionFromParentSample.class); assertThat(RuntimeHintsPredicates.reflection() - .onMethod(PackagePrivateMethodInjectionSample.class, "setTestBean")) + .onMethodInvocation(PackagePrivateMethodInjectionSample.class, "setTestBean")) .accepts(this.generationContext.getRuntimeHints()); compile(registeredBean, (postProcessor, compiled) -> { PackagePrivateMethodInjectionFromParentSample instance = new PackagePrivateMethodInjectionFromParentSample(); diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGeneratorTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGeneratorTests.java index 0a2f316b5a50..84e2dab7ed97 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGeneratorTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGeneratorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -568,7 +568,7 @@ private void assertReflectionOnPublisher() { private void assertHasMethodInvokeHints(Class beanType, String... methodNames) { assertThat(methodNames).allMatch(methodName -> RuntimeHintsPredicates.reflection() - .onMethod(beanType, methodName).invoke() + .onMethodInvocation(beanType, methodName) .test(this.generationContext.getRuntimeHints())); } diff --git a/spring-context/src/test/java/org/springframework/context/annotation/CommonAnnotationBeanRegistrationAotContributionTests.java b/spring-context/src/test/java/org/springframework/context/annotation/CommonAnnotationBeanRegistrationAotContributionTests.java index 7f4e591bc4f4..0356e01ae23f 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/CommonAnnotationBeanRegistrationAotContributionTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/CommonAnnotationBeanRegistrationAotContributionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -79,7 +79,7 @@ void contributeWhenPrivateFieldInjectionInjectsUsingReflection() { RegisteredBean registeredBean = getAndApplyContribution( PrivateFieldResourceSample.class); assertThat(RuntimeHintsPredicates.reflection() - .onField(PrivateFieldResourceSample.class, "one")) + .onType(PrivateFieldResourceSample.class)) .accepts(this.generationContext.getRuntimeHints()); compile(registeredBean, (postProcessor, compiled) -> { PrivateFieldResourceSample instance = new PrivateFieldResourceSample(); @@ -98,7 +98,7 @@ void contributeWhenPackagePrivateFieldInjectionInjectsUsingFieldAssignement() { RegisteredBean registeredBean = getAndApplyContribution( PackagePrivateFieldResourceSample.class); assertThat(RuntimeHintsPredicates.reflection() - .onField(PackagePrivateFieldResourceSample.class, "one")) + .onType(PackagePrivateFieldResourceSample.class)) .accepts(this.generationContext.getRuntimeHints()); compile(registeredBean, (postProcessor, compiled) -> { PackagePrivateFieldResourceSample instance = new PackagePrivateFieldResourceSample(); @@ -117,7 +117,7 @@ void contributeWhenPackagePrivateFieldInjectionOnParentClassInjectsUsingReflecti RegisteredBean registeredBean = getAndApplyContribution( PackagePrivateFieldResourceFromParentSample.class); assertThat(RuntimeHintsPredicates.reflection() - .onField(PackagePrivateFieldResourceSample.class, "one")) + .onType(PackagePrivateFieldResourceSample.class)) .accepts(this.generationContext.getRuntimeHints()); compile(registeredBean, (postProcessor, compiled) -> { PackagePrivateFieldResourceFromParentSample instance = new PackagePrivateFieldResourceFromParentSample(); @@ -135,7 +135,7 @@ void contributeWhenPrivateMethodInjectionInjectsUsingReflection() { RegisteredBean registeredBean = getAndApplyContribution( PrivateMethodResourceSample.class); assertThat(RuntimeHintsPredicates.reflection() - .onMethod(PrivateMethodResourceSample.class, "setOne").invoke()) + .onMethodInvocation(PrivateMethodResourceSample.class, "setOne")) .accepts(this.generationContext.getRuntimeHints()); compile(registeredBean, (postProcessor, compiled) -> { PrivateMethodResourceSample instance = new PrivateMethodResourceSample(); @@ -153,7 +153,7 @@ void contributeWhenPrivateMethodInjectionWithCustomNameInjectsUsingReflection() RegisteredBean registeredBean = getAndApplyContribution( PrivateMethodResourceWithCustomNameSample.class); assertThat(RuntimeHintsPredicates.reflection() - .onMethod(PrivateMethodResourceWithCustomNameSample.class, "setText").invoke()) + .onMethodInvocation(PrivateMethodResourceWithCustomNameSample.class, "setText")) .accepts(this.generationContext.getRuntimeHints()); compile(registeredBean, (postProcessor, compiled) -> { PrivateMethodResourceWithCustomNameSample instance = new PrivateMethodResourceWithCustomNameSample(); @@ -172,7 +172,7 @@ void contributeWhenPackagePrivateMethodInjectionInjectsUsingMethodInvocation() { RegisteredBean registeredBean = getAndApplyContribution( PackagePrivateMethodResourceSample.class); assertThat(RuntimeHintsPredicates.reflection() - .onMethod(PackagePrivateMethodResourceSample.class, "setOne").introspect()) + .onType(PackagePrivateMethodResourceSample.class)) .accepts(this.generationContext.getRuntimeHints()); compile(registeredBean, (postProcessor, compiled) -> { PackagePrivateMethodResourceSample instance = new PackagePrivateMethodResourceSample(); @@ -191,7 +191,7 @@ void contributeWhenPackagePrivateMethodInjectionOnParentClassInjectsUsingReflect RegisteredBean registeredBean = getAndApplyContribution( PackagePrivateMethodResourceFromParentSample.class); assertThat(RuntimeHintsPredicates.reflection() - .onMethod(PackagePrivateMethodResourceSample.class, "setOne")) + .onMethodInvocation(PackagePrivateMethodResourceSample.class, "setOne")) .accepts(this.generationContext.getRuntimeHints()); compile(registeredBean, (postProcessor, compiled) -> { PackagePrivateMethodResourceFromParentSample instance = new PackagePrivateMethodResourceFromParentSample(); diff --git a/spring-context/src/test/java/org/springframework/context/aot/ApplicationContextAotGeneratorTests.java b/spring-context/src/test/java/org/springframework/context/aot/ApplicationContextAotGeneratorTests.java index b2da6f1c7bac..e1cffd8c7e3c 100644 --- a/spring-context/src/test/java/org/springframework/context/aot/ApplicationContextAotGeneratorTests.java +++ b/spring-context/src/test/java/org/springframework/context/aot/ApplicationContextAotGeneratorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ package org.springframework.context.aot; import java.io.IOException; -import java.lang.reflect.Constructor; import java.lang.reflect.Proxy; import java.util.List; import java.util.function.BiConsumer; @@ -565,8 +564,7 @@ void processAheadOfTimeWhenHasCglibProxyWithArgumentsRegisterIntrospectionHintsO GenericApplicationContext applicationContext = new AnnotationConfigApplicationContext(); applicationContext.registerBean(ConfigurableCglibConfiguration.class); TestGenerationContext generationContext = processAheadOfTime(applicationContext); - Constructor userConstructor = ConfigurableCglibConfiguration.class.getDeclaredConstructors()[0]; - assertThat(RuntimeHintsPredicates.reflection().onConstructor(userConstructor).introspect()) + assertThat(RuntimeHintsPredicates.reflection().onType(ConfigurableCglibConfiguration.class)) .accepts(generationContext.getRuntimeHints()); } diff --git a/spring-context/src/test/java/org/springframework/context/aot/ReflectiveProcessorBeanFactoryInitializationAotProcessorTests.java b/spring-context/src/test/java/org/springframework/context/aot/ReflectiveProcessorBeanFactoryInitializationAotProcessorTests.java index dedaa501ce16..22f61e1c4f9f 100644 --- a/spring-context/src/test/java/org/springframework/context/aot/ReflectiveProcessorBeanFactoryInitializationAotProcessorTests.java +++ b/spring-context/src/test/java/org/springframework/context/aot/ReflectiveProcessorBeanFactoryInitializationAotProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,6 @@ package org.springframework.context.aot; -import java.lang.reflect.Constructor; - import org.junit.jupiter.api.Test; import org.springframework.aot.generate.GenerationContext; @@ -69,8 +67,7 @@ void shouldProcessAnnotationOnType() { void shouldProcessAllBeans() throws NoSuchMethodException { ReflectionHintsPredicates reflection = RuntimeHintsPredicates.reflection(); process(SampleTypeAnnotatedBean.class, SampleConstructorAnnotatedBean.class); - Constructor constructor = SampleConstructorAnnotatedBean.class.getDeclaredConstructor(String.class); - assertThat(reflection.onType(SampleTypeAnnotatedBean.class).and(reflection.onConstructor(constructor))) + assertThat(reflection.onType(SampleTypeAnnotatedBean.class)) .accepts(this.generationContext.getRuntimeHints()); } diff --git a/spring-core-test/src/main/java/org/springframework/aot/agent/InstrumentedMethod.java b/spring-core-test/src/main/java/org/springframework/aot/agent/InstrumentedMethod.java index e81479205889..4e6864df5094 100644 --- a/spring-core-test/src/main/java/org/springframework/aot/agent/InstrumentedMethod.java +++ b/spring-core-test/src/main/java/org/springframework/aot/agent/InstrumentedMethod.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -179,8 +179,7 @@ enum InstrumentedMethod { if (field == null) { return runtimeHints -> false; } - return reflection().onType(field.getDeclaringClass()) - .or(reflection().onField(field)); + return reflection().onType(field.getDeclaringClass()); }), /** @@ -232,25 +231,25 @@ enum InstrumentedMethod { * {@link Constructor#newInstance(Object...)}. */ CONSTRUCTOR_NEWINSTANCE(Constructor.class, "newInstance", HintType.REFLECTION, - invocation -> reflection().onConstructor(invocation.getInstance()).invoke()), + invocation -> reflection().onConstructorInvocation(invocation.getInstance())), /** * {@link Method#invoke(Object, Object...)}. */ METHOD_INVOKE(Method.class, "invoke", HintType.REFLECTION, - invocation -> reflection().onMethod(invocation.getInstance()).invoke()), + invocation -> reflection().onMethodInvocation(invocation.getInstance())), /** * {@link Field#get(Object)}. */ FIELD_GET(Field.class, "get", HintType.REFLECTION, - invocation -> reflection().onField(invocation.getInstance())), + invocation -> reflection().onFieldInvocation(invocation.getInstance())), /** * {@link Field#set(Object, Object)}. */ FIELD_SET(Field.class, "set", HintType.REFLECTION, - invocation -> reflection().onField(invocation.getInstance())), + invocation -> reflection().onFieldInvocation(invocation.getInstance())), /* diff --git a/spring-core/src/main/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicates.java b/spring-core/src/main/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicates.java index 47dc61429f8d..debc13244366 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicates.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicates.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -81,24 +81,52 @@ public TypeHintPredicate onType(Class type) { *

The returned type exposes additional methods that refine the predicate behavior. * @param constructor the constructor * @return the {@link RuntimeHints} predicate + * @deprecated since 7.0 in favor of {@link #onConstructorInvocation(Constructor)} + * or {@link #onType(Class)}. */ + @Deprecated(since = "7.0", forRemoval = true) public ConstructorHintPredicate onConstructor(Constructor constructor) { Assert.notNull(constructor, "'constructor' must not be null"); return new ConstructorHintPredicate(constructor); } + /** + * Return a predicate that checks whether an invocation hint is registered for the given constructor. + * @param constructor the constructor + * @return the {@link RuntimeHints} predicate + * @since 7.0 + */ + public Predicate onConstructorInvocation(Constructor constructor) { + Assert.notNull(constructor, "'constructor' must not be null"); + return new ConstructorHintPredicate(constructor).invoke(); + } + /** * Return a predicate that checks whether a reflection hint is registered for the given method. * By default, both introspection and invocation hints match. *

The returned type exposes additional methods that refine the predicate behavior. * @param method the method * @return the {@link RuntimeHints} predicate + * @deprecated since 7.0 in favor of {@link #onMethodInvocation(Method)} + * or {@link #onType(Class)}. */ + @Deprecated(since = "7.0", forRemoval = true) public MethodHintPredicate onMethod(Method method) { Assert.notNull(method, "'method' must not be null"); return new MethodHintPredicate(method); } + /** + * Return a predicate that checks whether an invocation hint is registered for the given method. + * @param method the method + * @return the {@link RuntimeHints} predicate + * @since 7.0 + */ + public Predicate onMethodInvocation(Method method) { + Assert.notNull(method, "'method' must not be null"); + return new MethodHintPredicate(method).invoke(); + } + /** * Return a predicate that checks whether a reflection hint is registered for the method that matches the given selector. * This looks up a method on the given type with the expected name, if unique. @@ -108,13 +136,31 @@ public MethodHintPredicate onMethod(Method method) { * @param methodName the method name * @return the {@link RuntimeHints} predicate * @throws IllegalArgumentException if the method cannot be found or if multiple methods are found with the same name. + * @deprecated since 7.0 in favor of {@link #onMethodInvocation(Class, String)} + * or {@link #onType(Class)}. */ + @Deprecated(since = "7.0", forRemoval = true) public MethodHintPredicate onMethod(Class type, String methodName) { Assert.notNull(type, "'type' must not be null"); Assert.hasText(methodName, "'methodName' must not be empty"); return new MethodHintPredicate(getMethod(type, methodName)); } + /** + * Return a predicate that checks whether an invocation hint is registered for the method that matches the given selector. + * This looks up a method on the given type with the expected name, if unique. + * @param type the type holding the method + * @param methodName the method name + * @return the {@link RuntimeHints} predicate + * @throws IllegalArgumentException if the method cannot be found or if multiple methods are found with the same name. + * @since 7.0 + */ + public Predicate onMethodInvocation(Class type, String methodName) { + Assert.notNull(type, "'type' must not be null"); + Assert.hasText(methodName, "'methodName' must not be empty"); + return new MethodHintPredicate(getMethod(type, methodName)).invoke(); + } + /** * Return a predicate that checks whether a reflection hint is registered for the method that matches the given selector. * This looks up a method on the given type with the expected name, if unique. @@ -125,13 +171,32 @@ public MethodHintPredicate onMethod(Class type, String methodName) { * @return the {@link RuntimeHints} predicate * @throws ClassNotFoundException if the class cannot be resolved. * @throws IllegalArgumentException if the method cannot be found or if multiple methods are found with the same name. + * @deprecated since 7.0 in favor of {@link #onMethodInvocation(String, String)} + * or {@link #onType(Class)}. */ + @Deprecated(since = "7.0", forRemoval = true) public MethodHintPredicate onMethod(String className, String methodName) throws ClassNotFoundException { Assert.hasText(className, "'className' must not be empty"); Assert.hasText(methodName, "'methodName' must not be empty"); return onMethod(Class.forName(className), methodName); } + /** + * Return a predicate that checks whether an invocation hint is registered for the method that matches the given selector. + * This looks up a method on the given type with the expected name, if unique. + * @param className the name of the class holding the method + * @param methodName the method name + * @return the {@link RuntimeHints} predicate + * @throws ClassNotFoundException if the class cannot be resolved. + * @throws IllegalArgumentException if the method cannot be found or if multiple methods are found with the same name. + * @since 7.0 + */ + public Predicate onMethodInvocation(String className, String methodName) throws ClassNotFoundException { + Assert.hasText(className, "'className' must not be empty"); + Assert.hasText(methodName, "'methodName' must not be empty"); + return onMethod(Class.forName(className), methodName).invoke(); + } + private Method getMethod(Class type, String methodName) { ReflectionUtils.MethodFilter selector = method -> methodName.equals(method.getName()); Set methods = MethodIntrospector.selectMethods(type, selector); @@ -155,7 +220,10 @@ else if (methods.size() > 1) { * @param fieldName the field name * @return the {@link RuntimeHints} predicate * @throws IllegalArgumentException if a field cannot be found with the given name. + * @deprecated since 7.0 in favor of {@link #onFieldInvocation(Class, String)} + * or {@link #onType(Class)}. */ + @Deprecated(since = "7.0", forRemoval = true) public FieldHintPredicate onField(Class type, String fieldName) { Assert.notNull(type, "'type' must not be null"); Assert.hasText(fieldName, "'fieldName' must not be empty"); @@ -166,6 +234,25 @@ public FieldHintPredicate onField(Class type, String fieldName) { return new FieldHintPredicate(field); } + /** + * Return a predicate that checks whether an invocation hint is registered for the field that matches the given selector. + * This looks up a field on the given type with the expected name, if present. + * @param type the type holding the field + * @param fieldName the field name + * @return the {@link RuntimeHints} predicate + * @throws IllegalArgumentException if a field cannot be found with the given name. + * @since 7.0 + */ + public Predicate onFieldInvocation(Class type, String fieldName) { + Assert.notNull(type, "'type' must not be null"); + Assert.hasText(fieldName, "'fieldName' must not be empty"); + Field field = ReflectionUtils.findField(type, fieldName); + if (field == null) { + throw new IllegalArgumentException("No field named '%s' on class %s".formatted(fieldName, type.getName())); + } + return new FieldHintPredicate(field).invocation(); + } + /** * Return a predicate that checks whether a reflection hint is registered for the field that matches the given selector. * This looks up a field on the given type with the expected name, if present. @@ -176,25 +263,58 @@ public FieldHintPredicate onField(Class type, String fieldName) { * @return the {@link RuntimeHints} predicate * @throws ClassNotFoundException if the class cannot be resolved. * @throws IllegalArgumentException if a field cannot be found with the given name. + * @deprecated since 7.0 in favor of {@link #onFieldInvocation(String, String)} + * or {@link #onType(Class)}. */ + @Deprecated(since = "7.0", forRemoval = true) public FieldHintPredicate onField(String className, String fieldName) throws ClassNotFoundException { Assert.hasText(className, "'className' must not be empty"); Assert.hasText(fieldName, "'fieldName' must not be empty"); return onField(Class.forName(className), fieldName); } + /** + * Return a predicate that checks whether an invocation hint is registered for the field that matches the given selector. + * This looks up a field on the given type with the expected name, if present. + * @param className the name of the class holding the field + * @param fieldName the field name + * @return the {@link RuntimeHints} predicate + * @throws ClassNotFoundException if the class cannot be resolved. + * @throws IllegalArgumentException if a field cannot be found with the given name. + * @since 7.0 + */ + public Predicate onFieldInvocation(String className, String fieldName) throws ClassNotFoundException { + Assert.hasText(className, "'className' must not be empty"); + Assert.hasText(fieldName, "'fieldName' must not be empty"); + return onField(Class.forName(className), fieldName).invocation(); + } + /** * Return a predicate that checks whether a reflection hint is registered for the given field. * By default, unsafe or write access is not considered. *

The returned type exposes additional methods that refine the predicate behavior. * @param field the field * @return the {@link RuntimeHints} predicate + * @deprecated since 7.0 in favor of {@link #onFieldInvocation(Field)} + * or {@link #onType(Class)}. */ + @Deprecated(since = "7.0", forRemoval = true) public FieldHintPredicate onField(Field field) { Assert.notNull(field, "'field' must not be null"); return new FieldHintPredicate(field); } + /** + * Return a predicate that checks whether an invocation hint is registered for the given field. + * @param field the field + * @return the {@link RuntimeHints} predicate + * @since 7.0 + */ + public Predicate onFieldInvocation(Field field) { + Assert.notNull(field, "'field' must not be null"); + return new FieldHintPredicate(field).invocation(); + } + public static class TypeHintPredicate implements Predicate { diff --git a/spring-core/src/test/java/org/springframework/aot/hint/BindingReflectionHintsRegistrarTests.java b/spring-core/src/test/java/org/springframework/aot/hint/BindingReflectionHintsRegistrarTests.java index 24498581ecd2..ddae91227f24 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/BindingReflectionHintsRegistrarTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/BindingReflectionHintsRegistrarTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -254,7 +254,7 @@ void registerTypeForSerializationWithRecord() { @Test void registerTypeForSerializationWithRecordWithProperty() { bindingRegistrar.registerReflectionHints(this.hints.reflection(), SampleRecordWithProperty.class); - assertThat(RuntimeHintsPredicates.reflection().onMethod(SampleRecordWithProperty.class, "getNameProperty")) + assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(SampleRecordWithProperty.class, "getNameProperty")) .accepts(this.hints); } @@ -267,18 +267,18 @@ void registerTypeForSerializationWithAnonymousClass() { @Test void registerTypeForJacksonAnnotations() { bindingRegistrar.registerReflectionHints(this.hints.reflection(), SampleClassWithJsonProperty.class); - assertThat(RuntimeHintsPredicates.reflection().onField(SampleClassWithJsonProperty.class, "privateField")) + assertThat(RuntimeHintsPredicates.reflection().onFieldInvocation(SampleClassWithJsonProperty.class, "privateField")) .accepts(this.hints); - assertThat(RuntimeHintsPredicates.reflection().onMethod(SampleClassWithJsonProperty.class, "packagePrivateMethod").invoke()) + assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(SampleClassWithJsonProperty.class, "packagePrivateMethod")) .accepts(this.hints); } @Test void registerTypeForInheritedJacksonAnnotations() { bindingRegistrar.registerReflectionHints(this.hints.reflection(), SampleClassWithInheritedJsonProperty.class); - assertThat(RuntimeHintsPredicates.reflection().onField(SampleClassWithJsonProperty.class, "privateField")) + assertThat(RuntimeHintsPredicates.reflection().onFieldInvocation(SampleClassWithJsonProperty.class, "privateField")) .accepts(this.hints); - assertThat(RuntimeHintsPredicates.reflection().onMethod(SampleClassWithJsonProperty.class, "packagePrivateMethod").invoke()) + assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(SampleClassWithJsonProperty.class, "packagePrivateMethod")) .accepts(this.hints); } diff --git a/spring-core/src/test/java/org/springframework/aot/hint/annotation/ReflectiveRuntimeHintsRegistrarTests.java b/spring-core/src/test/java/org/springframework/aot/hint/annotation/ReflectiveRuntimeHintsRegistrarTests.java index 5bc8f852fe5c..9ea7122ed022 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/annotation/ReflectiveRuntimeHintsRegistrarTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/annotation/ReflectiveRuntimeHintsRegistrarTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -152,7 +152,7 @@ void shouldProcessDifferentAnnotationsOnTypeAndField() { void shouldInvokeCustomProcessor() { process(SampleCustomProcessor.class); assertThat(RuntimeHintsPredicates.reflection() - .onMethod(SampleCustomProcessor.class, "managed")).accepts(this.runtimeHints); + .onMethodInvocation(SampleCustomProcessor.class, "managed")).accepts(this.runtimeHints); assertThat(RuntimeHintsPredicates.reflection().onType(String.class) .withMemberCategory(MemberCategory.INVOKE_DECLARED_METHODS)).accepts(this.runtimeHints); diff --git a/spring-core/src/test/java/org/springframework/aot/hint/annotation/RegisterReflectionForBindingProcessorTests.java b/spring-core/src/test/java/org/springframework/aot/hint/annotation/RegisterReflectionForBindingProcessorTests.java index f19fdb5227d7..1d60f83f54ac 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/annotation/RegisterReflectionForBindingProcessorTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/annotation/RegisterReflectionForBindingProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,7 +41,7 @@ void registerReflectionForBindingOnClass() { processor.registerReflectionHints(hints.reflection(), ClassLevelAnnotatedBean.class); assertThat(RuntimeHintsPredicates.reflection().onType(SampleClassWithGetter.class)).accepts(hints); assertThat(RuntimeHintsPredicates.reflection().onType(String.class)).accepts(hints); - assertThat(RuntimeHintsPredicates.reflection().onMethod(SampleClassWithGetter.class, "getName")).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(SampleClassWithGetter.class, "getName")).accepts(hints); } @Test @@ -49,7 +49,7 @@ void registerReflectionForBindingOnMethod() throws NoSuchMethodException { processor.registerReflectionHints(hints.reflection(), MethodLevelAnnotatedBean.class.getMethod("method")); assertThat(RuntimeHintsPredicates.reflection().onType(SampleClassWithGetter.class)).accepts(hints); assertThat(RuntimeHintsPredicates.reflection().onType(String.class)).accepts(hints); - assertThat(RuntimeHintsPredicates.reflection().onMethod(SampleClassWithGetter.class, "getName")).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(SampleClassWithGetter.class, "getName")).accepts(hints); } @Test @@ -57,7 +57,7 @@ void registerReflectionForBindingOnClassItself() { processor.registerReflectionHints(hints.reflection(), SampleClassWithoutAnnotationAttribute.class); assertThat(RuntimeHintsPredicates.reflection().onType(SampleClassWithoutAnnotationAttribute.class)).accepts(hints); assertThat(RuntimeHintsPredicates.reflection().onType(String.class)).accepts(hints); - assertThat(RuntimeHintsPredicates.reflection().onMethod(SampleClassWithoutAnnotationAttribute.class, "getName")).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(SampleClassWithoutAnnotationAttribute.class, "getName")).accepts(hints); } @Test diff --git a/spring-core/src/test/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicatesTests.java b/spring-core/src/test/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicatesTests.java index 3ba1db988ab6..c3b800e8e050 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicatesTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicatesTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -156,147 +156,80 @@ void typeWithAnyMemberCategoryDoesNotMatchOtherCategory() { @Nested class ReflectionOnConstructor { - @Test - void constructorIntrospectionDoesNotMatchMissingHint() { - assertPredicateDoesNotMatch(reflection.onConstructor(publicConstructor).introspect()); - } - - @Test - void constructorIntrospectionMatchesTypeHint() { - runtimeHints.reflection().registerType(SampleClass.class); - assertPredicateMatches(reflection.onConstructor(publicConstructor).introspect()); - } - - @Test - void constructorIntrospectionMatchesConstructorHint() { - runtimeHints.reflection().registerType(SampleClass.class, typeHint -> - typeHint.withConstructor(Collections.emptyList(), ExecutableMode.INTROSPECT)); - assertPredicateMatches(reflection.onConstructor(publicConstructor).introspect()); - } - - @Test - void constructorIntrospectionMatchesIntrospectPublicConstructors() { - runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS); - assertPredicateMatches(reflection.onConstructor(publicConstructor).introspect()); - } - - @Test - void constructorIntrospectionMatchesInvokePublicConstructors() { - runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS); - assertPredicateMatches(reflection.onConstructor(publicConstructor).introspect()); - } - - @Test - void constructorIntrospectionMatchesIntrospectDeclaredConstructors() { - runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS); - assertPredicateMatches(reflection.onConstructor(publicConstructor).introspect()); - } - - @Test - void constructorIntrospectionMatchesInvokeDeclaredConstructors() { - runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS); - assertPredicateMatches(reflection.onConstructor(publicConstructor).introspect()); - } - @Test void constructorInvocationDoesNotMatchConstructorHint() { runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint. withConstructor(Collections.emptyList(), ExecutableMode.INTROSPECT)); - assertPredicateDoesNotMatch(reflection.onConstructor(publicConstructor).invoke()); + assertPredicateDoesNotMatch(reflection.onConstructorInvocation(publicConstructor)); } @Test void constructorInvocationMatchesConstructorInvocationHint() { runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint. withConstructor(Collections.emptyList(), ExecutableMode.INVOKE)); - assertPredicateMatches(reflection.onConstructor(publicConstructor).invoke()); + assertPredicateMatches(reflection.onConstructorInvocation(publicConstructor)); } @Test void constructorInvocationDoesNotMatchIntrospectPublicConstructors() { runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS); - assertPredicateDoesNotMatch(reflection.onConstructor(publicConstructor).invoke()); + assertPredicateDoesNotMatch(reflection.onConstructorInvocation(publicConstructor)); } @Test void constructorInvocationMatchesInvokePublicConstructors() { runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS); - assertPredicateMatches(reflection.onConstructor(publicConstructor).invoke()); + assertPredicateMatches(reflection.onConstructorInvocation(publicConstructor)); } @Test void constructorInvocationDoesNotMatchIntrospectDeclaredConstructors() { runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS); - assertPredicateDoesNotMatch(reflection.onConstructor(publicConstructor).invoke()); + assertPredicateDoesNotMatch(reflection.onConstructorInvocation(publicConstructor)); } @Test void constructorInvocationMatchesInvokeDeclaredConstructors() { runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS); - assertPredicateMatches(reflection.onConstructor(publicConstructor).invoke()); - } - - @Test - void privateConstructorIntrospectionMatchesTypeHint() { - runtimeHints.reflection().registerType(SampleClass.class); - assertPredicateMatches(reflection.onConstructor(privateConstructor).introspect()); - } - - @Test - void privateConstructorIntrospectionMatchesConstructorHint() { - runtimeHints.reflection().registerType(SampleClass.class, typeHint -> - typeHint.withConstructor(TypeReference.listOf(String.class), ExecutableMode.INTROSPECT)); - assertPredicateMatches(reflection.onConstructor(privateConstructor).introspect()); - } - - @Test - void privateConstructorIntrospectionMatchesIntrospectDeclaredConstructors() { - runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS); - assertPredicateMatches(reflection.onConstructor(privateConstructor).introspect()); - } - - @Test - void privateConstructorIntrospectionMatchesInvokeDeclaredConstructors() { - runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS); - assertPredicateMatches(reflection.onConstructor(privateConstructor).introspect()); + assertPredicateMatches(reflection.onConstructorInvocation(publicConstructor)); } @Test void privateConstructorInvocationDoesNotMatchConstructorHint() { runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withConstructor(TypeReference.listOf(String.class), ExecutableMode.INTROSPECT)); - assertPredicateDoesNotMatch(reflection.onConstructor(privateConstructor).invoke()); + assertPredicateDoesNotMatch(reflection.onConstructorInvocation(privateConstructor)); } @Test void privateConstructorInvocationMatchesConstructorInvocationHint() { runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withConstructor(TypeReference.listOf(String.class), ExecutableMode.INVOKE)); - assertPredicateMatches(reflection.onConstructor(privateConstructor).invoke()); + assertPredicateMatches(reflection.onConstructorInvocation(privateConstructor)); } @Test void privateConstructorInvocationDoesNotMatchIntrospectPublicConstructors() { runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS); - assertPredicateDoesNotMatch(reflection.onConstructor(privateConstructor).invoke()); + assertPredicateDoesNotMatch(reflection.onConstructorInvocation(privateConstructor)); } @Test void privateConstructorInvocationDoesNotMatchInvokePublicConstructors() { runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS); - assertPredicateDoesNotMatch(reflection.onConstructor(privateConstructor).invoke()); + assertPredicateDoesNotMatch(reflection.onConstructorInvocation(privateConstructor)); } @Test void privateConstructorInvocationDoesNotMatchIntrospectDeclaredConstructors() { runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS); - assertPredicateDoesNotMatch(reflection.onConstructor(privateConstructor).invoke()); + assertPredicateDoesNotMatch(reflection.onConstructorInvocation(privateConstructor)); } @Test void privateConstructorInvocationMatchesInvokeDeclaredConstructors() { runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS); - assertPredicateMatches(reflection.onConstructor(privateConstructor).invoke()); + assertPredicateMatches(reflection.onConstructorInvocation(privateConstructor)); } } @@ -448,7 +381,7 @@ void shouldFailForMissingField() { @Test void shouldFailForUnknownClass() { - assertThatThrownBy(() -> reflection.onField("com.example.DoesNotExist", "missingField")) + assertThatThrownBy(() -> reflection.onFieldInvocation("com.example.DoesNotExist", "missingField")) .isInstanceOf(ClassNotFoundException.class); } diff --git a/spring-core/src/test/java/org/springframework/aot/hint/support/ObjectToObjectConverterRuntimeHintsTests.java b/spring-core/src/test/java/org/springframework/aot/hint/support/ObjectToObjectConverterRuntimeHintsTests.java index af23f4802e3e..e01467e60225 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/support/ObjectToObjectConverterRuntimeHintsTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/support/ObjectToObjectConverterRuntimeHintsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -49,13 +49,13 @@ void setup() { @Test void javaSqlDateHasHints() throws NoSuchMethodException { - assertThat(RuntimeHintsPredicates.reflection().onMethod(java.sql.Date.class, "toLocalDate")).accepts(this.hints); - assertThat(RuntimeHintsPredicates.reflection().onMethod(java.sql.Date.class.getMethod("valueOf", LocalDate.class))).accepts(this.hints); + assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(java.sql.Date.class, "toLocalDate")).accepts(this.hints); + assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(java.sql.Date.class.getMethod("valueOf", LocalDate.class))).accepts(this.hints); } @Test void uriHasHints() throws NoSuchMethodException { - assertThat(RuntimeHintsPredicates.reflection().onConstructor(URI.class.getConstructor(String.class))).accepts(this.hints); + assertThat(RuntimeHintsPredicates.reflection().onType(URI.class)).accepts(this.hints); } } diff --git a/spring-core/src/test/kotlin/org/springframework/aot/hint/BindingReflectionHintsRegistrarKotlinTests.kt b/spring-core/src/test/kotlin/org/springframework/aot/hint/BindingReflectionHintsRegistrarKotlinTests.kt index 000df8e09b18..40d9b3361040 100644 --- a/spring-core/src/test/kotlin/org/springframework/aot/hint/BindingReflectionHintsRegistrarKotlinTests.kt +++ b/spring-core/src/test/kotlin/org/springframework/aot/hint/BindingReflectionHintsRegistrarKotlinTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -65,14 +65,14 @@ class BindingReflectionHintsRegistrarKotlinTests { @Test fun `Register reflection hints for Kotlin data class`() { bindingRegistrar.registerReflectionHints(hints.reflection(), SampleDataClass::class.java) - assertThat(RuntimeHintsPredicates.reflection().onMethod(SampleDataClass::class.java, "component1")).accepts(hints) - assertThat(RuntimeHintsPredicates.reflection().onMethod(SampleDataClass::class.java, "copy")).accepts(hints) - assertThat(RuntimeHintsPredicates.reflection().onMethod(SampleDataClass::class.java, "getName")).accepts(hints) - assertThat(RuntimeHintsPredicates.reflection().onMethod(SampleDataClass::class.java, "isNonNullable")).accepts(hints) - assertThat(RuntimeHintsPredicates.reflection().onMethod(SampleDataClass::class.java, "isNullable")).accepts(hints) + assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(SampleDataClass::class.java, "component1")).accepts(hints) + assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(SampleDataClass::class.java, "copy")).accepts(hints) + assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(SampleDataClass::class.java, "getName")).accepts(hints) + assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(SampleDataClass::class.java, "isNonNullable")).accepts(hints) + assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(SampleDataClass::class.java, "isNullable")).accepts(hints) val copyDefault: Method = SampleDataClass::class.java.getMethod("copy\$default", SampleDataClass::class.java, String::class.java, Boolean::class.javaPrimitiveType, Boolean::class.javaObjectType, Int::class.java, Object::class.java) - assertThat(RuntimeHintsPredicates.reflection().onMethod(copyDefault)).accepts(hints) + assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(copyDefault)).accepts(hints) } @Test diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactoryRuntimeHintsTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactoryRuntimeHintsTests.java index 2bfb57b7670c..76853ad7b583 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactoryRuntimeHintsTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactoryRuntimeHintsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,7 +47,7 @@ void setup() { @Test void embeddedDataSourceProxyTypeHasHint() throws ClassNotFoundException { assertThat(RuntimeHintsPredicates.reflection() - .onMethod("org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory$EmbeddedDataSourceProxy", "shutdown")) + .onMethodInvocation("org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory$EmbeddedDataSourceProxy", "shutdown")) .accepts(this.hints); } diff --git a/spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/MessageMappingReflectiveProcessorTests.java b/spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/MessageMappingReflectiveProcessorTests.java index 694705a4b07c..b46b2725aeb2 100644 --- a/spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/MessageMappingReflectiveProcessorTests.java +++ b/spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/MessageMappingReflectiveProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -123,14 +123,14 @@ void registerReflectiveHintsForClass() { void registerReflectiveHintsForMethodWithSubscribeMapping() throws NoSuchMethodException { Method method = SampleController.class.getDeclaredMethod("handleSubscribe"); processor.registerReflectionHints(hints.reflection(), method); - assertThat(RuntimeHintsPredicates.reflection().onMethod(SampleController.class, "handleSubscribe")).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(SampleController.class, "handleSubscribe")).accepts(hints); } @Test void registerReflectiveHintsForMethodWithMessageExceptionHandler() throws NoSuchMethodException { Method method = SampleController.class.getDeclaredMethod("handleIOException"); processor.registerReflectionHints(hints.reflection(), method); - assertThat(RuntimeHintsPredicates.reflection().onMethod(SampleController.class, "handleIOException")).accepts(hints); + assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(SampleController.class, "handleIOException")).accepts(hints); assertThat(RuntimeHintsPredicates.reflection().onType(IOException.class)).accepts(hints); } diff --git a/spring-messaging/src/test/java/org/springframework/messaging/rsocket/service/RSocketExchangeReflectiveProcessorTests.java b/spring-messaging/src/test/java/org/springframework/messaging/rsocket/service/RSocketExchangeReflectiveProcessorTests.java index 4c164202dd80..8994e20c3bcb 100644 --- a/spring-messaging/src/test/java/org/springframework/messaging/rsocket/service/RSocketExchangeReflectiveProcessorTests.java +++ b/spring-messaging/src/test/java/org/springframework/messaging/rsocket/service/RSocketExchangeReflectiveProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,19 +50,19 @@ void shouldRegisterReflectionHintsForMethod() throws NoSuchMethodException { processor.registerReflectionHints(hints.reflection(), method); assertThat(reflection().onType(SampleService.class)).accepts(hints); - assertThat(reflection().onMethod(SampleService.class, "get")).accepts(hints); + assertThat(reflection().onMethodInvocation(SampleService.class, "get")).accepts(hints); assertThat(reflection().onType(Response.class)).accepts(hints); - assertThat(reflection().onMethod(Response.class, "getMessage")).accepts(hints); - assertThat(reflection().onMethod(Response.class, "setMessage")).accepts(hints); + assertThat(reflection().onMethodInvocation(Response.class, "getMessage")).accepts(hints); + assertThat(reflection().onMethodInvocation(Response.class, "setMessage")).accepts(hints); assertThat(reflection().onType(Request.class)).accepts(hints); - assertThat(reflection().onMethod(Request.class, "getMessage")).accepts(hints); - assertThat(reflection().onMethod(Request.class, "setMessage")).accepts(hints); + assertThat(reflection().onMethodInvocation(Request.class, "getMessage")).accepts(hints); + assertThat(reflection().onMethodInvocation(Request.class, "setMessage")).accepts(hints); assertThat(reflection().onType(Variable.class)).accepts(hints); - assertThat(reflection().onMethod(Variable.class, "getValue")).accepts(hints); - assertThat(reflection().onMethod(Variable.class, "setValue")).accepts(hints); + assertThat(reflection().onMethodInvocation(Variable.class, "getValue")).accepts(hints); + assertThat(reflection().onMethodInvocation(Variable.class, "setValue")).accepts(hints); assertThat(reflection().onType(Metadata.class)).accepts(hints); - assertThat(reflection().onMethod(Metadata.class, "getValue")).accepts(hints); - assertThat(reflection().onMethod(Metadata.class, "setValue")).accepts(hints); + assertThat(reflection().onMethodInvocation(Metadata.class, "getValue")).accepts(hints); + assertThat(reflection().onMethodInvocation(Metadata.class, "setValue")).accepts(hints); } diff --git a/spring-orm/src/test/java/org/springframework/orm/jpa/EntityManagerRuntimeHintsTests.java b/spring-orm/src/test/java/org/springframework/orm/jpa/EntityManagerRuntimeHintsTests.java index 5b43a20dcd0d..3d17a76fab79 100644 --- a/spring-orm/src/test/java/org/springframework/orm/jpa/EntityManagerRuntimeHintsTests.java +++ b/spring-orm/src/test/java/org/springframework/orm/jpa/EntityManagerRuntimeHintsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -60,7 +60,7 @@ void entityManagerProxyHasHibernateHints() { @Test void entityManagerFactoryHasReflectionHints() { - assertThat(RuntimeHintsPredicates.reflection().onMethod(EntityManagerFactory.class, "getCriteriaBuilder")).accepts(this.hints); - assertThat(RuntimeHintsPredicates.reflection().onMethod(EntityManagerFactory.class, "getMetamodel")).accepts(this.hints); + assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(EntityManagerFactory.class, "getCriteriaBuilder")).accepts(this.hints); + assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(EntityManagerFactory.class, "getMetamodel")).accepts(this.hints); } } diff --git a/spring-orm/src/test/java/org/springframework/orm/jpa/persistenceunit/PersistenceManagedTypesBeanRegistrationAotProcessorTests.java b/spring-orm/src/test/java/org/springframework/orm/jpa/persistenceunit/PersistenceManagedTypesBeanRegistrationAotProcessorTests.java index 3801d9ec570b..2dd772fe9702 100644 --- a/spring-orm/src/test/java/org/springframework/orm/jpa/persistenceunit/PersistenceManagedTypesBeanRegistrationAotProcessorTests.java +++ b/spring-orm/src/test/java/org/springframework/orm/jpa/persistenceunit/PersistenceManagedTypesBeanRegistrationAotProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -93,7 +93,7 @@ void contributeJpaHints() { .accepts(hints); assertThat(RuntimeHintsPredicates.reflection().onType(Employee.class) .withMemberCategories(MemberCategory.INVOKE_DECLARED_FIELDS)).accepts(hints); - assertThat(RuntimeHintsPredicates.reflection().onMethod(Employee.class, "preRemove")) + assertThat(RuntimeHintsPredicates.reflection().onMethodInvocation(Employee.class, "preRemove")) .accepts(hints); assertThat(RuntimeHintsPredicates.reflection().onType(EmployeeId.class) .withMemberCategories(MemberCategory.INVOKE_DECLARED_FIELDS)).accepts(hints); diff --git a/spring-orm/src/test/java/org/springframework/orm/jpa/support/InjectionCodeGeneratorTests.java b/spring-orm/src/test/java/org/springframework/orm/jpa/support/InjectionCodeGeneratorTests.java index 5aaa30088283..c54810d44ed4 100644 --- a/spring-orm/src/test/java/org/springframework/orm/jpa/support/InjectionCodeGeneratorTests.java +++ b/spring-orm/src/test/java/org/springframework/orm/jpa/support/InjectionCodeGeneratorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -125,7 +125,7 @@ void generateCodeWhenPrivateFieldAddsHint() { Field field = ReflectionUtils.findField(bean.getClass(), "age"); createGenerator(TEST_TARGET).generateInjectionCode( field, INSTANCE_VARIABLE, CodeBlock.of("$L", 123)); - assertThat(RuntimeHintsPredicates.reflection().onField(TestBean.class, "age")) + assertThat(RuntimeHintsPredicates.reflection().onType(TestBean.class)) .accepts(this.hints); } @@ -197,7 +197,7 @@ void generateCodeWhenPrivateMethodAddsHint() { createGenerator(TEST_TARGET).generateInjectionCode( method, INSTANCE_VARIABLE, CodeBlock.of("$L", 123)); assertThat(RuntimeHintsPredicates.reflection() - .onMethod(TestBeanWithPrivateMethod.class, "setAge").invoke()).accepts(this.hints); + .onMethodInvocation(TestBeanWithPrivateMethod.class, "setAge")).accepts(this.hints); } private InjectionCodeGenerator createGenerator(ClassName target) { diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/DeclarativeRuntimeHintsTests.java b/spring-test/src/test/java/org/springframework/test/context/aot/DeclarativeRuntimeHintsTests.java index e983a5fa9743..57cf1206b7e9 100644 --- a/spring-test/src/test/java/org/springframework/test/context/aot/DeclarativeRuntimeHintsTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/aot/DeclarativeRuntimeHintsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -56,7 +56,7 @@ void declarativeRuntimeHints() { // @RegisterReflectionForBinding assertReflectionRegistered(SampleClassWithGetter.class); assertReflectionRegistered(String.class); - assertThat(reflection().onMethod(SampleClassWithGetter.class, "getName")).accepts(this.runtimeHints); + assertThat(reflection().onMethodInvocation(SampleClassWithGetter.class, "getName")).accepts(this.runtimeHints); // @ImportRuntimeHints assertThat(resource().forResource("org/example/config/enigma.txt")).accepts(this.runtimeHints); diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/TestContextAotGeneratorIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/context/aot/TestContextAotGeneratorIntegrationTests.java index e5b0bf2250c5..a71890a09cf6 100644 --- a/spring-test/src/test/java/org/springframework/test/context/aot/TestContextAotGeneratorIntegrationTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/aot/TestContextAotGeneratorIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -290,7 +290,7 @@ private static void assertRuntimeHints(RuntimeHints runtimeHints) { ).forEach(type -> assertReflectionRegistered(runtimeHints, type, INVOKE_DECLARED_CONSTRUCTORS)); // @TestBean(methodName = ) - assertThat(reflection().onMethod(GreetingServiceFactory.class, "createEnigmaGreetingService")) + assertThat(reflection().onMethodInvocation(GreetingServiceFactory.class, "createEnigmaGreetingService")) .accepts(runtimeHints); // GenericApplicationContext.preDetermineBeanTypes() should have registered proxy diff --git a/spring-web/src/test/java/org/springframework/http/converter/json/ProblemDetailRuntimeHintsTests.java b/spring-web/src/test/java/org/springframework/http/converter/json/ProblemDetailRuntimeHintsTests.java index c094e8a0e3d2..bad57ce9c849 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/json/ProblemDetailRuntimeHintsTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/json/ProblemDetailRuntimeHintsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,7 +53,7 @@ void setup() { void getterMethodsShouldHaveReflectionHints() { for (String methodName : METHOD_NAMES) { assertThat(RuntimeHintsPredicates.reflection() - .onMethod(ProblemDetail.class, methodName)).accepts(this.hints); + .onMethodInvocation(ProblemDetail.class, methodName)).accepts(this.hints); } } @@ -61,7 +61,7 @@ void getterMethodsShouldHaveReflectionHints() { void mixinShouldHaveReflectionHints() { for (String methodName : METHOD_NAMES) { assertThat(RuntimeHintsPredicates.reflection() - .onMethod(ProblemDetailJacksonXmlMixin.class, methodName)).accepts(this.hints); + .onMethodInvocation(ProblemDetailJacksonXmlMixin.class, methodName)).accepts(this.hints); } } diff --git a/spring-web/src/test/java/org/springframework/web/service/annotation/HttpExchangeReflectiveProcessorTests.java b/spring-web/src/test/java/org/springframework/web/service/annotation/HttpExchangeReflectiveProcessorTests.java index 6067104e7955..952827c0de04 100644 --- a/spring-web/src/test/java/org/springframework/web/service/annotation/HttpExchangeReflectiveProcessorTests.java +++ b/spring-web/src/test/java/org/springframework/web/service/annotation/HttpExchangeReflectiveProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,10 +43,10 @@ void registerReflectiveHintsForMethodWithReturnValue() throws NoSuchMethodExcept Method method = SampleService.class.getDeclaredMethod("get"); processor.registerReflectionHints(hints.reflection(), method); assertThat(reflection().onType(SampleService.class)).accepts(hints); - assertThat(reflection().onMethod(SampleService.class, "get")).accepts(hints); + assertThat(reflection().onMethodInvocation(SampleService.class, "get")).accepts(hints); assertThat(reflection().onType(Response.class)).accepts(hints); - assertThat(reflection().onMethod(Response.class, "getMessage")).accepts(hints); - assertThat(reflection().onMethod(Response.class, "setMessage")).accepts(hints); + assertThat(reflection().onMethodInvocation(Response.class, "getMessage")).accepts(hints); + assertThat(reflection().onMethodInvocation(Response.class, "setMessage")).accepts(hints); } @Test @@ -54,10 +54,10 @@ void registerReflectiveHintsForMethodWithRequestBodyParameter() throws NoSuchMet Method method = SampleService.class.getDeclaredMethod("post", Request.class); processor.registerReflectionHints(hints.reflection(), method); assertThat(reflection().onType(SampleService.class)).accepts(hints); - assertThat(reflection().onMethod(SampleService.class, "post")).accepts(hints); + assertThat(reflection().onMethodInvocation(SampleService.class, "post")).accepts(hints); assertThat(reflection().onType(Request.class)).accepts(hints); - assertThat(reflection().onMethod(Request.class, "getMessage")).accepts(hints); - assertThat(reflection().onMethod(Request.class, "setMessage")).accepts(hints); + assertThat(reflection().onMethodInvocation(Request.class, "getMessage")).accepts(hints); + assertThat(reflection().onMethodInvocation(Request.class, "setMessage")).accepts(hints); }