Harmonize hint registration
Previously, a shortcut method for the default ExecutableMode was provided, but we found out that the shortcut makes it harder to determine the intent. This commit harmonizes hints registration for types, methods, and fields. An ExecutableMode is now mandatory to register a method or constructor. Previous methods that infer a mode or provided a customizer of the builder are deprecated. Closes gh-29135
This commit is contained in:
parent
c8f7a76659
commit
58a2b79699
|
|
@ -1007,7 +1007,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
|
|||
AccessVisibility visibility = AccessVisibility.forMember(method);
|
||||
if (visibility == AccessVisibility.PRIVATE
|
||||
|| visibility == AccessVisibility.PROTECTED) {
|
||||
hints.reflection().registerMethod(method);
|
||||
hints.reflection().registerMethod(method, ExecutableMode.INVOKE);
|
||||
code.add(".resolveAndInvoke($L, $L)", REGISTERED_BEAN_PARAMETER,
|
||||
INSTANCE_PARAMETER);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ class BeanDefinitionPropertiesCodeGenerator {
|
|||
private void addInitDestroyHint(Class<?> beanUserClass, String methodName) {
|
||||
Method method = ReflectionUtils.findMethod(beanUserClass, methodName);
|
||||
if (method != null) {
|
||||
this.hints.reflection().registerMethod(method);
|
||||
this.hints.reflection().registerMethod(method, ExecutableMode.INVOKE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ class InstanceSupplierCodeGenerator {
|
|||
Class<?> beanClass, Constructor<?> constructor, boolean dependsOnBean) {
|
||||
|
||||
this.generationContext.getRuntimeHints().reflection()
|
||||
.registerConstructor(constructor);
|
||||
.registerConstructor(constructor, ExecutableMode.INVOKE);
|
||||
GeneratedMethod generatedMethod = generateGetInstanceSupplierMethod(method -> {
|
||||
method.addJavadoc("Get the bean instance supplier for '$L'.", beanName);
|
||||
method.addModifiers(PRIVATE_STATIC);
|
||||
|
|
@ -240,7 +240,7 @@ class InstanceSupplierCodeGenerator {
|
|||
Method factoryMethod, Class<?> declaringClass) {
|
||||
|
||||
this.generationContext.getRuntimeHints().reflection()
|
||||
.registerMethod(factoryMethod);
|
||||
.registerMethod(factoryMethod, ExecutableMode.INVOKE);
|
||||
GeneratedMethod getInstanceMethod = generateGetInstanceSupplierMethod(method -> {
|
||||
method.addJavadoc("Get the bean instance supplier for '$L'.", beanName);
|
||||
method.addModifiers(PRIVATE_STATIC);
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ class InstrumentedMethodTests {
|
|||
|
||||
@Test
|
||||
void classGetConstructorsShouldMatchConstructorReflectionHint() throws Exception {
|
||||
hints.reflection().registerConstructor(String.class.getConstructor());
|
||||
hints.reflection().registerConstructor(String.class.getConstructor(), ExecutableMode.INVOKE);
|
||||
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETCONSTRUCTORS, this.stringGetConstructors);
|
||||
}
|
||||
|
||||
|
|
@ -250,7 +250,7 @@ class InstrumentedMethodTests {
|
|||
|
||||
@Test
|
||||
void classGetDeclaredConstructorsShouldMatchConstructorReflectionHint() throws Exception {
|
||||
hints.reflection().registerConstructor(String.class.getConstructor());
|
||||
hints.reflection().registerConstructor(String.class.getConstructor(), ExecutableMode.INVOKE);
|
||||
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDCONSTRUCTORS, this.stringGetDeclaredConstructors);
|
||||
}
|
||||
|
||||
|
|
@ -350,7 +350,7 @@ class InstrumentedMethodTests {
|
|||
|
||||
@Test
|
||||
void classGetDeclaredMethodsShouldMatchMethodReflectionHint() throws Exception {
|
||||
hints.reflection().registerMethod(String.class.getMethod("toString"));
|
||||
hints.reflection().registerMethod(String.class.getMethod("toString"), ExecutableMode.INVOKE);
|
||||
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDMETHODS, this.stringGetScaleMethod);
|
||||
}
|
||||
|
||||
|
|
@ -392,7 +392,7 @@ class InstrumentedMethodTests {
|
|||
|
||||
@Test
|
||||
void classGetMethodsShouldMatchMethodReflectionHint() throws Exception {
|
||||
hints.reflection().registerMethod(String.class.getMethod("toString"));
|
||||
hints.reflection().registerMethod(String.class.getMethod("toString"), ExecutableMode.INVOKE);
|
||||
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETMETHODS, this.stringGetMethods);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ public class BindingReflectionHintsRegistrar {
|
|||
Class<?> companionClass = ClassUtils.resolveClassName(companionClassName, null);
|
||||
Method serializerMethod = ClassUtils.getMethodIfAvailable(companionClass, "serializer");
|
||||
if (serializerMethod != null) {
|
||||
hints.registerMethod(serializerMethod);
|
||||
hints.registerMethod(serializerMethod, ExecutableMode.INVOKE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ import org.springframework.util.ClassUtils;
|
|||
* Gather the need for reflection at runtime.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
* @since 6.0
|
||||
*/
|
||||
public class ReflectionHints {
|
||||
|
|
@ -79,6 +81,7 @@ public class ReflectionHints {
|
|||
* @param type the type to customize
|
||||
* @param typeHint a builder to further customize hints for that type
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
* @see #registerType(TypeReference, MemberCategory...)
|
||||
*/
|
||||
public ReflectionHints registerType(TypeReference type, Consumer<TypeHint.Builder> typeHint) {
|
||||
Builder builder = this.types.computeIfAbsent(type, TypeHint.Builder::new);
|
||||
|
|
@ -93,8 +96,19 @@ public class ReflectionHints {
|
|||
* @param memberCategories the member categories to apply
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
*/
|
||||
public ReflectionHints registerType(Class<?> type, MemberCategory... memberCategories) {
|
||||
return registerType(TypeReference.of(type), memberCategories);
|
||||
public ReflectionHints registerType(TypeReference type, MemberCategory... memberCategories) {
|
||||
return registerType(type, TypeHint.builtWith(memberCategories));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register or customize reflection hints for the specified type.
|
||||
* @param type the type to customize
|
||||
* @param typeHint a builder to further customize hints for that type
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
* @see #registerType(Class, MemberCategory...)
|
||||
*/
|
||||
public ReflectionHints registerType(Class<?> type, Consumer<TypeHint.Builder> typeHint) {
|
||||
return registerType(TypeReference.of(type), typeHint);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -104,18 +118,8 @@ public class ReflectionHints {
|
|||
* @param memberCategories the member categories to apply
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
*/
|
||||
public ReflectionHints registerType(TypeReference type , MemberCategory... memberCategories) {
|
||||
return registerType(type, TypeHint.builtWith(memberCategories));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register or customize reflection hints for the specified type.
|
||||
* @param type the type to customize
|
||||
* @param typeHint a builder to further customize hints for that type
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
*/
|
||||
public ReflectionHints registerType(Class<?> type, Consumer<TypeHint.Builder> typeHint) {
|
||||
return registerType(TypeReference.of(type), typeHint);
|
||||
public ReflectionHints registerType(Class<?> type, MemberCategory... memberCategories) {
|
||||
return registerType(TypeReference.of(type), memberCategories);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -125,6 +129,7 @@ public class ReflectionHints {
|
|||
* @param typeName the type to customize
|
||||
* @param typeHint a builder to further customize hints for that type
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
* @see #registerTypeIfPresent(ClassLoader, String, MemberCategory...)
|
||||
*/
|
||||
public ReflectionHints registerTypeIfPresent(@Nullable ClassLoader classLoader,
|
||||
String typeName, Consumer<TypeHint.Builder> typeHint) {
|
||||
|
|
@ -134,6 +139,19 @@ public class ReflectionHints {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register or customize reflection hints for the specified type if it
|
||||
* is available using the specified {@link ClassLoader}.
|
||||
* @param classLoader the classloader to use to check if the type is present
|
||||
* @param typeName the type to customize
|
||||
* @param memberCategories the member categories to apply
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
*/
|
||||
public ReflectionHints registerTypeIfPresent(@Nullable ClassLoader classLoader,
|
||||
String typeName, MemberCategory... memberCategories) {
|
||||
return registerTypeIfPresent(classLoader, typeName, TypeHint.builtWith(memberCategories));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register or customize reflection hints for the types defined by the
|
||||
* specified list of {@link TypeReference type references}. The specified
|
||||
|
|
@ -162,7 +180,9 @@ public class ReflectionHints {
|
|||
* enabling {@link ExecutableMode#INVOKE}.
|
||||
* @param constructor the constructor that requires reflection
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
* @deprecated in favor of {@link #registerConstructor(Constructor, ExecutableMode)}
|
||||
*/
|
||||
@Deprecated
|
||||
public ReflectionHints registerConstructor(Constructor<?> constructor) {
|
||||
return registerConstructor(constructor, ExecutableMode.INVOKE);
|
||||
}
|
||||
|
|
@ -175,7 +195,8 @@ public class ReflectionHints {
|
|||
* @return {@code this}, to facilitate method chaining
|
||||
*/
|
||||
public ReflectionHints registerConstructor(Constructor<?> constructor, ExecutableMode mode) {
|
||||
return registerConstructor(constructor, ExecutableHint.builtWith(mode));
|
||||
return registerType(TypeReference.of(constructor.getDeclaringClass()),
|
||||
typeHint -> typeHint.withConstructor(mapParameters(constructor), mode));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -183,8 +204,10 @@ public class ReflectionHints {
|
|||
* @param constructor the constructor that requires reflection
|
||||
* @param constructorHint a builder to further customize the hints of this
|
||||
* constructor
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
* @return {@code this}, to facilitate method chaining`
|
||||
* @deprecated in favor of {@link #registerConstructor(Constructor, ExecutableMode)}
|
||||
*/
|
||||
@Deprecated
|
||||
public ReflectionHints registerConstructor(Constructor<?> constructor, Consumer<ExecutableHint.Builder> constructorHint) {
|
||||
return registerType(TypeReference.of(constructor.getDeclaringClass()),
|
||||
typeHint -> typeHint.withConstructor(mapParameters(constructor), constructorHint));
|
||||
|
|
@ -195,7 +218,9 @@ public class ReflectionHints {
|
|||
* enabling {@link ExecutableMode#INVOKE}.
|
||||
* @param method the method that requires reflection
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
* @deprecated in favor of {@link #registerMethod(Method, ExecutableMode)}
|
||||
*/
|
||||
@Deprecated
|
||||
public ReflectionHints registerMethod(Method method) {
|
||||
return registerMethod(method, ExecutableMode.INVOKE);
|
||||
}
|
||||
|
|
@ -208,7 +233,8 @@ public class ReflectionHints {
|
|||
* @return {@code this}, to facilitate method chaining
|
||||
*/
|
||||
public ReflectionHints registerMethod(Method method, ExecutableMode mode) {
|
||||
return registerMethod(method, ExecutableHint.builtWith(mode));
|
||||
return registerType(TypeReference.of(method.getDeclaringClass()),
|
||||
typeHint -> typeHint.withMethod(method.getName(), mapParameters(method), mode));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -216,7 +242,9 @@ public class ReflectionHints {
|
|||
* @param method the method that requires reflection
|
||||
* @param methodHint a builder to further customize the hints of this method
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
* @deprecated in favor of {@link #registerMethod(Method, ExecutableMode)}
|
||||
*/
|
||||
@Deprecated
|
||||
public ReflectionHints registerMethod(Method method, Consumer<ExecutableHint.Builder> methodHint) {
|
||||
return registerType(TypeReference.of(method.getDeclaringClass()),
|
||||
typeHint -> typeHint.withMethod(method.getName(), mapParameters(method), methodHint));
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ import org.springframework.util.Assert;
|
|||
* A hint that describes the need for reflection on a type.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
* @since 6.0
|
||||
*/
|
||||
public final class TypeHint implements ConditionalHint {
|
||||
|
|
@ -199,7 +201,9 @@ public final class TypeHint implements ConditionalHint {
|
|||
* parameter types, enabling {@link ExecutableMode#INVOKE}.
|
||||
* @param parameterTypes the parameter types of the constructor
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
* @deprecated in favor of {@link #withConstructor(List, ExecutableMode)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Builder withConstructor(List<TypeReference> parameterTypes) {
|
||||
return withConstructor(parameterTypes, ExecutableMode.INVOKE);
|
||||
}
|
||||
|
|
@ -222,8 +226,11 @@ public final class TypeHint implements ConditionalHint {
|
|||
* @param constructorHint a builder to further customize the hints of this
|
||||
* constructor
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
* @deprecated in favor of {@link #withConstructor(List, ExecutableMode)}
|
||||
*/
|
||||
public Builder withConstructor(List<TypeReference> parameterTypes, Consumer<ExecutableHint.Builder> constructorHint) {
|
||||
@Deprecated
|
||||
public Builder withConstructor(List<TypeReference> parameterTypes,
|
||||
Consumer<ExecutableHint.Builder> constructorHint) {
|
||||
ExecutableKey key = new ExecutableKey("<init>", parameterTypes);
|
||||
ExecutableHint.Builder builder = this.constructors.computeIfAbsent(key,
|
||||
k -> ExecutableHint.ofConstructor(parameterTypes));
|
||||
|
|
@ -237,7 +244,9 @@ public final class TypeHint implements ConditionalHint {
|
|||
* @param name the name of the method
|
||||
* @param parameterTypes the parameter types of the constructor
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
* @deprecated in favor of {@link #withMethod(String, List, ExecutableMode)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Builder withMethod(String name, List<TypeReference> parameterTypes) {
|
||||
return withMethod(name, parameterTypes, ExecutableMode.INVOKE);
|
||||
}
|
||||
|
|
@ -261,8 +270,11 @@ public final class TypeHint implements ConditionalHint {
|
|||
* @param parameterTypes the parameter types of the constructor
|
||||
* @param methodHint a builder to further customize the hints of this method
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
* @deprecated in favor of {@link #withMethod(String, List, ExecutableMode)}
|
||||
*/
|
||||
public Builder withMethod(String name, List<TypeReference> parameterTypes, Consumer<ExecutableHint.Builder> methodHint) {
|
||||
@Deprecated
|
||||
public Builder withMethod(String name, List<TypeReference> parameterTypes,
|
||||
Consumer<ExecutableHint.Builder> methodHint) {
|
||||
ExecutableKey key = new ExecutableKey(name, parameterTypes);
|
||||
ExecutableHint.Builder builder = this.methods.computeIfAbsent(key,
|
||||
k -> ExecutableHint.ofMethod(name, parameterTypes));
|
||||
|
|
@ -274,6 +286,7 @@ public final class TypeHint implements ConditionalHint {
|
|||
* Adds the specified {@linkplain MemberCategory member categories}.
|
||||
* @param memberCategories the categories to apply
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
* @see TypeHint#builtWith(MemberCategory...)
|
||||
*/
|
||||
public Builder withMembers(MemberCategory... memberCategories) {
|
||||
this.memberCategories.addAll(Arrays.asList(memberCategories));
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import java.lang.reflect.Constructor;
|
|||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.aot.hint.ExecutableMode;
|
||||
import org.springframework.aot.hint.ReflectionHints;
|
||||
|
||||
/**
|
||||
|
|
@ -64,7 +65,7 @@ public class SimpleReflectiveProcessor implements ReflectiveProcessor {
|
|||
* @param constructor the constructor to process
|
||||
*/
|
||||
protected void registerConstructorHint(ReflectionHints hints, Constructor<?> constructor) {
|
||||
hints.registerConstructor(constructor);
|
||||
hints.registerConstructor(constructor, ExecutableMode.INVOKE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -82,7 +83,7 @@ public class SimpleReflectiveProcessor implements ReflectiveProcessor {
|
|||
* @param method the method to process
|
||||
*/
|
||||
protected void registerMethodHint(ReflectionHints hints, Method method) {
|
||||
hints.registerMethod(method);
|
||||
hints.registerMethod(method, ExecutableMode.INVOKE);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.springframework.aot.hint;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.Consumer;
|
||||
|
|
@ -48,8 +49,7 @@ class ReflectionHintsTests {
|
|||
|
||||
@Test
|
||||
void registerTypeIfPresentRegistersExistingClass() {
|
||||
this.reflectionHints.registerTypeIfPresent(null, String.class.getName(),
|
||||
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS));
|
||||
this.reflectionHints.registerTypeIfPresent(null, String.class.getName(), MemberCategory.DECLARED_FIELDS);
|
||||
assertThat(this.reflectionHints.typeHints()).singleElement().satisfies(
|
||||
typeWithMemberCategories(String.class, MemberCategory.DECLARED_FIELDS));
|
||||
}
|
||||
|
|
@ -144,15 +144,6 @@ class ReflectionHintsTests {
|
|||
|
||||
@Test
|
||||
void registerConstructor() {
|
||||
this.reflectionHints.registerConstructor(TestType.class.getDeclaredConstructors()[0]);
|
||||
assertTestTypeConstructorHint(constructorHint -> {
|
||||
assertThat(constructorHint.getParameterTypes()).isEmpty();
|
||||
assertThat(constructorHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void registerConstructorWithMode() {
|
||||
this.reflectionHints.registerConstructor(
|
||||
TestType.class.getDeclaredConstructors()[0], ExecutableMode.INTROSPECT);
|
||||
assertTestTypeConstructorHint(constructorHint -> {
|
||||
|
|
@ -162,25 +153,16 @@ class ReflectionHintsTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void registerConstructorWithEmptyCustomizerAppliesConsistentDefault() {
|
||||
this.reflectionHints.registerConstructor(TestType.class.getDeclaredConstructors()[0],
|
||||
constructorHint -> {});
|
||||
void registerConstructorTwiceUpdatesExistingEntry() {
|
||||
Constructor<?> constructor = TestType.class.getDeclaredConstructors()[0];
|
||||
this.reflectionHints.registerConstructor(constructor, ExecutableMode.INTROSPECT);
|
||||
this.reflectionHints.registerConstructor(constructor, ExecutableMode.INVOKE);
|
||||
assertTestTypeConstructorHint(constructorHint -> {
|
||||
assertThat(constructorHint.getParameterTypes()).isEmpty();
|
||||
assertThat(constructorHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void registerConstructorWithCustomizerAppliesCustomization() {
|
||||
this.reflectionHints.registerConstructor(TestType.class.getDeclaredConstructors()[0],
|
||||
constructorHint -> constructorHint.withMode(ExecutableMode.INTROSPECT));
|
||||
assertTestTypeConstructorHint(constructorHint -> {
|
||||
assertThat(constructorHint.getParameterTypes()).isEmpty();
|
||||
assertThat(constructorHint.getMode()).isEqualTo(ExecutableMode.INTROSPECT);
|
||||
});
|
||||
}
|
||||
|
||||
private void assertTestTypeConstructorHint(Consumer<ExecutableHint> constructorHint) {
|
||||
assertThat(this.reflectionHints.typeHints()).singleElement().satisfies(typeHint -> {
|
||||
assertThat(typeHint.getMemberCategories()).isEmpty();
|
||||
|
|
@ -194,18 +176,6 @@ class ReflectionHintsTests {
|
|||
|
||||
@Test
|
||||
void registerMethod() {
|
||||
Method method = ReflectionUtils.findMethod(TestType.class, "setName", String.class);
|
||||
assertThat(method).isNotNull();
|
||||
this.reflectionHints.registerMethod(method);
|
||||
assertTestTypeMethodHints(methodHint -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("setName");
|
||||
assertThat(methodHint.getParameterTypes()).containsOnly(TypeReference.of(String.class));
|
||||
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void registerMethodWithMode() {
|
||||
Method method = ReflectionUtils.findMethod(TestType.class, "setName", String.class);
|
||||
assertThat(method).isNotNull();
|
||||
this.reflectionHints.registerMethod(method, ExecutableMode.INTROSPECT);
|
||||
|
|
@ -217,10 +187,11 @@ class ReflectionHintsTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void registerMethodWithEmptyCustomizerAppliesConsistentDefault() {
|
||||
void registerMethodTwiceUpdatesExistingEntry() {
|
||||
Method method = ReflectionUtils.findMethod(TestType.class, "setName", String.class);
|
||||
assertThat(method).isNotNull();
|
||||
this.reflectionHints.registerMethod(method, methodHint -> {});
|
||||
this.reflectionHints.registerMethod(method, ExecutableMode.INTROSPECT);
|
||||
this.reflectionHints.registerMethod(method, ExecutableMode.INVOKE);
|
||||
assertTestTypeMethodHints(methodHint -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("setName");
|
||||
assertThat(methodHint.getParameterTypes()).containsOnly(TypeReference.of(String.class));
|
||||
|
|
@ -228,18 +199,6 @@ class ReflectionHintsTests {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void registerMethodWithCustomizerAppliesCustomization() {
|
||||
Method method = ReflectionUtils.findMethod(TestType.class, "setName", String.class);
|
||||
assertThat(method).isNotNull();
|
||||
this.reflectionHints.registerMethod(method, methodHint -> methodHint.withMode(ExecutableMode.INTROSPECT));
|
||||
assertTestTypeMethodHints(methodHint -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("setName");
|
||||
assertThat(methodHint.getParameterTypes()).containsOnly(TypeReference.of(String.class));
|
||||
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INTROSPECT);
|
||||
});
|
||||
}
|
||||
|
||||
private void assertTestTypeMethodHints(Consumer<ExecutableHint> methodHint) {
|
||||
assertThat(this.reflectionHints.typeHints()).singleElement().satisfies(typeHint -> {
|
||||
assertThat(typeHint.getType().getCanonicalName()).isEqualTo(TestType.class.getCanonicalName());
|
||||
|
|
|
|||
|
|
@ -70,16 +70,6 @@ class TypeHintTests {
|
|||
|
||||
@Test
|
||||
void createWithConstructor() {
|
||||
List<TypeReference> parameterTypes = TypeReference.listOf(byte[].class, int.class);
|
||||
assertConstructorHint(TypeHint.of(TypeReference.of(String.class))
|
||||
.withConstructor(parameterTypes), constructorHint -> {
|
||||
assertThat(constructorHint.getParameterTypes()).containsOnlyOnceElementsOf(parameterTypes);
|
||||
assertThat(constructorHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWithConstructorAndMode() {
|
||||
List<TypeReference> parameterTypes = TypeReference.listOf(byte[].class, int.class);
|
||||
assertConstructorHint(TypeHint.of(TypeReference.of(String.class))
|
||||
.withConstructor(parameterTypes, ExecutableMode.INTROSPECT), constructorHint -> {
|
||||
|
|
@ -89,45 +79,22 @@ class TypeHintTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void createWithConstructorAndEmptyCustomizerAppliesConsistentDefault() {
|
||||
List<TypeReference> parameterTypes = TypeReference.listOf(byte[].class, int.class);
|
||||
assertConstructorHint(TypeHint.of(TypeReference.of(String.class))
|
||||
.withConstructor(parameterTypes, constructorHint -> {}), constructorHint -> {
|
||||
assertThat(constructorHint.getParameterTypes()).containsOnlyOnceElementsOf(parameterTypes);
|
||||
assertThat(constructorHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWithConstructorAndCustomizerAppliesCustomization() {
|
||||
List<TypeReference> parameterTypes = TypeReference.listOf(byte[].class, int.class);
|
||||
assertConstructorHint(TypeHint.of(TypeReference.of(String.class))
|
||||
.withConstructor(parameterTypes, constructorHint ->
|
||||
constructorHint.withMode(ExecutableMode.INTROSPECT)), constructorHint -> {
|
||||
assertThat(constructorHint.getParameterTypes()).containsOnlyOnceElementsOf(parameterTypes);
|
||||
assertThat(constructorHint.getMode()).isEqualTo(ExecutableMode.INTROSPECT);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void createConstructorReuseBuilder() {
|
||||
void createWithConstructorWithSameConstructorUpdatesEntry() {
|
||||
List<TypeReference> parameterTypes = TypeReference.listOf(byte[].class, int.class);
|
||||
Builder builder = TypeHint.of(TypeReference.of(String.class))
|
||||
.withConstructor(parameterTypes, ExecutableMode.INTROSPECT);
|
||||
assertConstructorHint(builder.withConstructor(parameterTypes, constructorHint ->
|
||||
constructorHint.withMode(ExecutableMode.INVOKE)), constructorHint -> {
|
||||
assertConstructorHint(builder.withConstructor(parameterTypes, ExecutableMode.INVOKE), constructorHint -> {
|
||||
assertThat(constructorHint.getParameterTypes()).containsExactlyElementsOf(parameterTypes);
|
||||
assertThat(constructorHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void createConstructorReuseBuilderAndApplyExecutableModePrecedence() {
|
||||
void createWithConstructorAndSameConstructorAppliesExecutableModePrecedence() {
|
||||
List<TypeReference> parameterTypes = TypeReference.listOf(byte[].class, int.class);
|
||||
Builder builder = TypeHint.of(TypeReference.of(String.class)).withConstructor(parameterTypes,
|
||||
constructorHint -> constructorHint.withMode(ExecutableMode.INVOKE));
|
||||
assertConstructorHint(builder.withConstructor(parameterTypes, constructorHint ->
|
||||
constructorHint.withMode(ExecutableMode.INTROSPECT)), constructorHint -> {
|
||||
Builder builder = TypeHint.of(TypeReference.of(String.class))
|
||||
.withConstructor(parameterTypes, ExecutableMode.INVOKE);
|
||||
assertConstructorHint(builder.withConstructor(parameterTypes, ExecutableMode.INTROSPECT), constructorHint -> {
|
||||
assertThat(constructorHint.getParameterTypes()).containsExactlyElementsOf(parameterTypes);
|
||||
assertThat(constructorHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
});
|
||||
|
|
@ -143,17 +110,6 @@ class TypeHintTests {
|
|||
|
||||
@Test
|
||||
void createWithMethod() {
|
||||
List<TypeReference> parameterTypes = List.of(TypeReference.of(char[].class));
|
||||
assertMethodHint(TypeHint.of(TypeReference.of(String.class))
|
||||
.withMethod("valueOf", parameterTypes), methodHint -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("valueOf");
|
||||
assertThat(methodHint.getParameterTypes()).containsExactlyElementsOf(parameterTypes);
|
||||
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWithMethodAndMode() {
|
||||
List<TypeReference> parameterTypes = List.of(TypeReference.of(char[].class));
|
||||
assertMethodHint(TypeHint.of(TypeReference.of(String.class))
|
||||
.withMethod("valueOf", parameterTypes, ExecutableMode.INTROSPECT), methodHint -> {
|
||||
|
|
@ -164,36 +120,11 @@ class TypeHintTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void createWithMethodAndEmptyCustomizerAppliesConsistentDefault() {
|
||||
List<TypeReference> parameterTypes = List.of(TypeReference.of(char[].class));
|
||||
assertMethodHint(TypeHint.of(TypeReference.of(String.class))
|
||||
.withMethod("valueOf", parameterTypes, methodHint -> {}), methodHint -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("valueOf");
|
||||
assertThat(methodHint.getParameterTypes()).containsExactlyElementsOf(parameterTypes);
|
||||
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWithMethodAndCustomizerAppliesCustomization() {
|
||||
List<TypeReference> parameterTypes = List.of(TypeReference.of(char[].class));
|
||||
assertMethodHint(TypeHint.of(TypeReference.of(String.class))
|
||||
.withMethod("valueOf", parameterTypes, methodHint ->
|
||||
methodHint.withMode(ExecutableMode.INTROSPECT)), methodHint -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("valueOf");
|
||||
assertThat(methodHint.getParameterTypes()).containsExactlyElementsOf(parameterTypes);
|
||||
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INTROSPECT);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void createWithMethodReuseBuilder() {
|
||||
void createWithMethodWithSameMethodUpdatesEntry() {
|
||||
List<TypeReference> parameterTypes = TypeReference.listOf(char[].class);
|
||||
Builder builder = TypeHint.of(TypeReference.of(String.class))
|
||||
.withMethod("valueOf", parameterTypes, ExecutableMode.INTROSPECT);
|
||||
assertMethodHint(builder.withMethod("valueOf", parameterTypes,
|
||||
methodHint -> methodHint.withMode(ExecutableMode.INVOKE)), methodHint -> {
|
||||
assertMethodHint(builder.withMethod("valueOf", parameterTypes, ExecutableMode.INVOKE), methodHint -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("valueOf");
|
||||
assertThat(methodHint.getParameterTypes()).containsExactlyElementsOf(parameterTypes);
|
||||
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
|
|
@ -201,12 +132,11 @@ class TypeHintTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void createWithMethodReuseBuilderAndApplyExecutableModePrecedence() {
|
||||
void createWithMethodAndSameMethodAppliesExecutableModePrecedence() {
|
||||
List<TypeReference> parameterTypes = TypeReference.listOf(char[].class);
|
||||
Builder builder = TypeHint.of(TypeReference.of(String.class))
|
||||
.withMethod("valueOf", parameterTypes, ExecutableMode.INVOKE);
|
||||
assertMethodHint(builder.withMethod("valueOf", parameterTypes,
|
||||
methodHint -> methodHint.withMode(ExecutableMode.INTROSPECT)), methodHint -> {
|
||||
assertMethodHint(builder.withMethod("valueOf", parameterTypes, ExecutableMode.INTROSPECT), methodHint -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("valueOf");
|
||||
assertThat(methodHint.getParameterTypes()).containsExactlyElementsOf(parameterTypes);
|
||||
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ class ReflectionHintsPredicatesTests {
|
|||
|
||||
@Test
|
||||
void reflectionOnAnyConstructorMatchesConstructorReflection() {
|
||||
runtimeHints.reflection().registerConstructor(publicConstructor);
|
||||
runtimeHints.reflection().registerConstructor(publicConstructor, ExecutableMode.INVOKE);
|
||||
assertPredicateMatches(reflection.onType(SampleClass.class).withAnyConstructor());
|
||||
}
|
||||
|
||||
|
|
@ -458,7 +458,7 @@ class ReflectionHintsPredicatesTests {
|
|||
|
||||
@Test
|
||||
void reflectionOnAnyMethodMatchesMethodReflection() {
|
||||
runtimeHints.reflection().registerMethod(publicMethod);
|
||||
runtimeHints.reflection().registerMethod(publicMethod, ExecutableMode.INVOKE);
|
||||
assertPredicateMatches(reflection.onType(SampleClass.class).withAnyMethod());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ public class FileNativeConfigurationWriterTests {
|
|||
.withField("DEFAULT_CHARSET")
|
||||
.withField("defaultCharset")
|
||||
.withConstructor(TypeReference.listOf(List.class, boolean.class, MimeType.class), ExecutableMode.INTROSPECT)
|
||||
.withMethod("setDefaultCharset", TypeReference.listOf(Charset.class))
|
||||
.withMethod("setDefaultCharset", TypeReference.listOf(Charset.class), ExecutableMode.INVOKE)
|
||||
.withMethod("getDefaultCharset", Collections.emptyList(), ExecutableMode.INTROSPECT));
|
||||
generator.write(hints);
|
||||
assertEquals("""
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ public class ReflectionHintsWriterTests {
|
|||
.withField("DEFAULT_CHARSET")
|
||||
.withField("defaultCharset")
|
||||
.withConstructor(TypeReference.listOf(List.class, boolean.class, MimeType.class), ExecutableMode.INTROSPECT)
|
||||
.withMethod("setDefaultCharset", List.of(TypeReference.of(Charset.class)))
|
||||
.withMethod("setDefaultCharset", List.of(TypeReference.of(Charset.class)), ExecutableMode.INVOKE)
|
||||
.withMethod("getDefaultCharset", Collections.emptyList(), ExecutableMode.INTROSPECT));
|
||||
assertEquals("""
|
||||
[
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import java.lang.reflect.Member;
|
|||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.aot.generate.AccessVisibility;
|
||||
import org.springframework.aot.hint.ExecutableMode;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.javapoet.CodeBlock;
|
||||
import org.springframework.util.Assert;
|
||||
|
|
@ -97,7 +98,7 @@ class InjectionCodeGenerator {
|
|||
AccessVisibility visibility = AccessVisibility.forMember(method);
|
||||
if (visibility == AccessVisibility.PRIVATE
|
||||
|| visibility == AccessVisibility.PROTECTED) {
|
||||
this.hints.reflection().registerMethod(method);
|
||||
this.hints.reflection().registerMethod(method, ExecutableMode.INVOKE);
|
||||
code.addStatement("$T method = $T.findMethod($T.class, $S, $T.class)",
|
||||
Method.class, ReflectionUtils.class, method.getDeclaringClass(),
|
||||
method.getName(), method.getParameterTypes()[0]);
|
||||
|
|
|
|||
Loading…
Reference in New Issue