Harmonize registration of reflection hints
Closes gh-29011
This commit is contained in:
commit
8a61866ee2
|
@ -46,7 +46,6 @@ import org.springframework.aot.generate.GeneratedClass;
|
|||
import org.springframework.aot.generate.GeneratedMethod;
|
||||
import org.springframework.aot.generate.GenerationContext;
|
||||
import org.springframework.aot.generate.MethodReference;
|
||||
import org.springframework.aot.hint.ExecutableHint;
|
||||
import org.springframework.aot.hint.ExecutableMode;
|
||||
import org.springframework.aot.hint.FieldHint;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
|
@ -914,9 +913,6 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
|
|||
|
||||
private static final String INSTANCE_PARAMETER = "instance";
|
||||
|
||||
private static final Consumer<ExecutableHint.Builder> INTROSPECT = builder -> builder
|
||||
.withMode(ExecutableMode.INTROSPECT);
|
||||
|
||||
private static final Consumer<FieldHint.Builder> ALLOW_WRITE = builder -> builder
|
||||
.allowWrite(true);
|
||||
|
||||
|
@ -1024,7 +1020,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
|
|||
INSTANCE_PARAMETER);
|
||||
}
|
||||
else {
|
||||
hints.reflection().registerMethod(method, INTROSPECT);
|
||||
hints.reflection().registerMethod(method, ExecutableMode.INTROSPECT);
|
||||
CodeBlock arguments = new AutowiredArgumentsCodeGenerator(this.target,
|
||||
method).generateCode(method.getParameterTypes());
|
||||
CodeBlock injectionCode = CodeBlock.of("args -> $L.$L($L)",
|
||||
|
|
|
@ -28,12 +28,10 @@ import java.util.Map;
|
|||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.springframework.aot.generate.GeneratedMethods;
|
||||
import org.springframework.aot.hint.ExecutableHint;
|
||||
import org.springframework.aot.hint.ExecutableMode;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.beans.BeanInfoFactory;
|
||||
|
@ -83,8 +81,6 @@ class BeanDefinitionPropertiesCodeGenerator {
|
|||
|
||||
private static final String BEAN_DEFINITION_VARIABLE = BeanRegistrationCodeFragments.BEAN_DEFINITION_VARIABLE;
|
||||
|
||||
private static final Consumer<ExecutableHint.Builder> INVOKE_HINT = hint -> hint.withMode(ExecutableMode.INVOKE);
|
||||
|
||||
private static final BeanInfoFactory beanInfoFactory = new ExtendedBeanInfoFactory();
|
||||
|
||||
private final RuntimeHints hints;
|
||||
|
@ -195,7 +191,7 @@ class BeanDefinitionPropertiesCodeGenerator {
|
|||
for (PropertyValue propertyValue : propertyValues) {
|
||||
Method writeMethod = writeMethods.get(propertyValue.getName());
|
||||
if (writeMethod != null) {
|
||||
this.hints.reflection().registerMethod(writeMethod, INVOKE_HINT);
|
||||
this.hints.reflection().registerMethod(writeMethod, ExecutableMode.INVOKE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ import org.springframework.aot.generate.AccessVisibility;
|
|||
import org.springframework.aot.generate.GeneratedMethod;
|
||||
import org.springframework.aot.generate.GeneratedMethods;
|
||||
import org.springframework.aot.generate.GenerationContext;
|
||||
import org.springframework.aot.hint.ExecutableHint;
|
||||
import org.springframework.aot.hint.ExecutableMode;
|
||||
import org.springframework.beans.factory.support.InstanceSupplier;
|
||||
import org.springframework.beans.factory.support.RegisteredBean;
|
||||
|
@ -69,9 +68,6 @@ class InstanceSupplierCodeGenerator {
|
|||
|
||||
private static final CodeBlock NO_ARGS = CodeBlock.of("");
|
||||
|
||||
private static final Consumer<ExecutableHint.Builder> INTROSPECT = hint -> hint
|
||||
.withMode(ExecutableMode.INTROSPECT);
|
||||
|
||||
|
||||
private final GenerationContext generationContext;
|
||||
|
||||
|
@ -128,7 +124,7 @@ class InstanceSupplierCodeGenerator {
|
|||
Constructor<?> constructor, boolean dependsOnBean, Class<?> declaringClass) {
|
||||
|
||||
this.generationContext.getRuntimeHints().reflection()
|
||||
.registerConstructor(constructor, INTROSPECT);
|
||||
.registerConstructor(constructor, ExecutableMode.INTROSPECT);
|
||||
if (!dependsOnBean && constructor.getParameterCount() == 0) {
|
||||
if (!this.allowDirectSupplierShortcut) {
|
||||
return CodeBlock.of("$T.using($T::new)", InstanceSupplier.class,
|
||||
|
@ -225,7 +221,7 @@ class InstanceSupplierCodeGenerator {
|
|||
Class<?> beanClass, Method factoryMethod, Class<?> declaringClass, boolean dependsOnBean) {
|
||||
|
||||
this.generationContext.getRuntimeHints().reflection()
|
||||
.registerMethod(factoryMethod, INTROSPECT);
|
||||
.registerMethod(factoryMethod, ExecutableMode.INTROSPECT);
|
||||
if (!dependsOnBean && factoryMethod.getParameterCount() == 0) {
|
||||
CodeBlock.Builder code = CodeBlock.builder();
|
||||
code.add("$T.<$T>forFactoryMethod($T.class, $S)", BeanInstanceSupplier.class,
|
||||
|
|
|
@ -283,7 +283,7 @@ class InstanceSupplierCodeGeneratorTests {
|
|||
}
|
||||
|
||||
private ThrowingConsumer<ExecutableHint> hasMode(ExecutableMode mode) {
|
||||
return hint -> assertThat(hint.getModes()).containsExactly(mode);
|
||||
return hint -> assertThat(hint.getMode()).isEqualTo(mode);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
|
|
@ -25,12 +25,10 @@ import java.lang.reflect.RecordComponent;
|
|||
import java.lang.reflect.Type;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.aot.hint.ExecutableHint;
|
||||
import org.springframework.aot.hint.ExecutableMode;
|
||||
import org.springframework.aot.hint.MemberCategory;
|
||||
import org.springframework.aot.hint.ReflectionHints;
|
||||
|
@ -54,9 +52,6 @@ public class BindingReflectionHintsRegistrar {
|
|||
|
||||
private static final Log logger = LogFactory.getLog(BindingReflectionHintsRegistrar.class);
|
||||
|
||||
private static final Consumer<ExecutableHint.Builder> INVOKE = builder -> builder
|
||||
.withMode(ExecutableMode.INVOKE);
|
||||
|
||||
private static final String KOTLIN_COMPANION_SUFFIX = "$Companion";
|
||||
|
||||
/**
|
||||
|
@ -127,7 +122,7 @@ public class BindingReflectionHintsRegistrar {
|
|||
}
|
||||
|
||||
private void registerRecordHints(ReflectionHints hints, Set<Type> seen, Method method) {
|
||||
hints.registerMethod(method, INVOKE);
|
||||
hints.registerMethod(method, ExecutableMode.INVOKE);
|
||||
MethodParameter methodParameter = MethodParameter.forExecutable(method, -1);
|
||||
Type methodParameterType = methodParameter.getGenericParameterType();
|
||||
if (!seen.contains(methodParameterType)) {
|
||||
|
@ -138,7 +133,7 @@ public class BindingReflectionHintsRegistrar {
|
|||
private void registerPropertyHints(ReflectionHints hints, Set<Type> seen, @Nullable Method method, int parameterIndex) {
|
||||
if (method != null && method.getDeclaringClass() != Object.class
|
||||
&& method.getDeclaringClass() != Enum.class) {
|
||||
hints.registerMethod(method, INVOKE);
|
||||
hints.registerMethod(method, ExecutableMode.INVOKE);
|
||||
MethodParameter methodParameter = MethodParameter.forExecutable(method, parameterIndex);
|
||||
Type methodParameterType = methodParameter.getGenericParameterType();
|
||||
if (!seen.contains(methodParameterType)) {
|
||||
|
|
|
@ -77,7 +77,7 @@ public class BindingReflectionHintsRegistrarTests {
|
|||
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(SampleClassWithGetter.class));
|
||||
assertThat(typeHint.methods()).singleElement().satisfies(methodHint -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("getName");
|
||||
assertThat(methodHint.getModes()).containsOnly(ExecutableMode.INVOKE);
|
||||
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ public class BindingReflectionHintsRegistrarTests {
|
|||
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(SampleClassWithSetter.class));
|
||||
assertThat(typeHint.methods()).singleElement().satisfies(methodHint -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("setName");
|
||||
assertThat(methodHint.getModes()).containsOnly(ExecutableMode.INVOKE);
|
||||
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -125,11 +125,11 @@ public class BindingReflectionHintsRegistrarTests {
|
|||
assertThat(typeHint.methods()).satisfiesExactlyInAnyOrder(
|
||||
methodHint -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("setNames");
|
||||
assertThat(methodHint.getModes()).containsOnly(ExecutableMode.INVOKE);
|
||||
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
},
|
||||
methodHint -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("getNames");
|
||||
assertThat(methodHint.getModes()).containsOnly(ExecutableMode.INVOKE);
|
||||
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ public class BindingReflectionHintsRegistrarTests {
|
|||
assertThat(typeHint.methods()).singleElement().satisfies(
|
||||
methodHint -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("getResolvableType");
|
||||
assertThat(methodHint.getModes()).containsOnly(ExecutableMode.INVOKE);
|
||||
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ public class BindingReflectionHintsRegistrarTests {
|
|||
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(SampleRecord.class));
|
||||
assertThat(typeHint.methods()).singleElement().satisfies(methodHint -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("name");
|
||||
assertThat(methodHint.getModes()).containsOnly(ExecutableMode.INVOKE);
|
||||
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -48,8 +48,7 @@ class KotlinBindingReflectionHintsRegistrarTests {
|
|||
assertThat(typeHint.methods()).singleElement()
|
||||
.satisfies(ThrowingConsumer { methodHint: ExecutableHint ->
|
||||
assertThat(methodHint.name).isEqualTo("getName")
|
||||
assertThat(methodHint.modes)
|
||||
.containsOnly(ExecutableMode.INVOKE)
|
||||
assertThat(methodHint.mode).isEqualTo(ExecutableMode.INVOKE)
|
||||
})
|
||||
},
|
||||
ThrowingConsumer { typeHint: TypeHint ->
|
||||
|
@ -57,7 +56,7 @@ class KotlinBindingReflectionHintsRegistrarTests {
|
|||
assertThat(typeHint.methods()).singleElement()
|
||||
.satisfies(ThrowingConsumer { methodHint: ExecutableHint ->
|
||||
assertThat(methodHint.name).isEqualTo("serializer")
|
||||
assertThat(methodHint.modes).containsOnly(ExecutableMode.INVOKE)
|
||||
assertThat(methodHint.mode).isEqualTo(ExecutableMode.INVOKE)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -151,15 +151,15 @@ class InstrumentedMethodTests {
|
|||
|
||||
@Test
|
||||
void classGetConstructorShouldMatchInstrospectConstructorHint() {
|
||||
hints.reflection().registerType(String.class, typeHint -> typeHint.withConstructor(Collections.emptyList(),
|
||||
constructorHint -> constructorHint.setModes(ExecutableMode.INTROSPECT)));
|
||||
hints.reflection().registerType(String.class,typeHint ->
|
||||
typeHint.withConstructor(Collections.emptyList(), ExecutableMode.INTROSPECT));
|
||||
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETCONSTRUCTOR, this.stringGetConstructor);
|
||||
}
|
||||
|
||||
@Test
|
||||
void classGetConstructorShouldMatchInvokeConstructorHint() {
|
||||
hints.reflection().registerType(String.class, typeHint -> typeHint.withConstructor(Collections.emptyList(),
|
||||
constructorHint -> constructorHint.setModes(ExecutableMode.INVOKE)));
|
||||
hints.reflection().registerType(String.class, typeHint ->
|
||||
typeHint.withConstructor(Collections.emptyList(),ExecutableMode.INVOKE));
|
||||
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETCONSTRUCTOR, this.stringGetConstructor);
|
||||
}
|
||||
|
||||
|
@ -201,15 +201,15 @@ class InstrumentedMethodTests {
|
|||
|
||||
@Test
|
||||
void classGetDeclaredConstructorShouldMatchInstrospectConstructorHint() {
|
||||
hints.reflection().registerType(String.class, typeHint -> typeHint.withConstructor(TypeReference.listOf(byte[].class, byte.class),
|
||||
constructorHint -> constructorHint.setModes(ExecutableMode.INTROSPECT)));
|
||||
hints.reflection().registerType(String.class, typeHint ->
|
||||
typeHint.withConstructor(TypeReference.listOf(byte[].class, byte.class), ExecutableMode.INTROSPECT));
|
||||
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDCONSTRUCTOR, this.stringGetDeclaredConstructor);
|
||||
}
|
||||
|
||||
@Test
|
||||
void classGetDeclaredConstructorShouldMatchInvokeConstructorHint() {
|
||||
hints.reflection().registerType(String.class, typeHint -> typeHint.withConstructor(TypeReference.listOf(byte[].class, byte.class),
|
||||
constructorHint -> constructorHint.setModes(ExecutableMode.INVOKE)));
|
||||
hints.reflection().registerType(String.class, typeHint ->
|
||||
typeHint.withConstructor(TypeReference.listOf(byte[].class, byte.class), ExecutableMode.INVOKE));
|
||||
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDCONSTRUCTOR, this.stringGetDeclaredConstructor);
|
||||
}
|
||||
|
||||
|
@ -237,7 +237,7 @@ class InstrumentedMethodTests {
|
|||
RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.CONSTRUCTOR_NEWINSTANCE)
|
||||
.onInstance(String.class.getConstructor()).returnValue("").build();
|
||||
hints.reflection().registerType(String.class, typeHint ->
|
||||
typeHint.withConstructor(Collections.emptyList(), constructorHint -> constructorHint.withMode(ExecutableMode.INVOKE)));
|
||||
typeHint.withConstructor(Collections.emptyList(), ExecutableMode.INVOKE));
|
||||
assertThatInvocationMatches(InstrumentedMethod.CONSTRUCTOR_NEWINSTANCE, invocation);
|
||||
}
|
||||
|
||||
|
@ -246,7 +246,7 @@ class InstrumentedMethodTests {
|
|||
RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.CONSTRUCTOR_NEWINSTANCE)
|
||||
.onInstance(String.class.getConstructor()).returnValue("").build();
|
||||
hints.reflection().registerType(String.class, typeHint ->
|
||||
typeHint.withConstructor(Collections.emptyList(), constructorHint -> constructorHint.withMode(ExecutableMode.INTROSPECT)));
|
||||
typeHint.withConstructor(Collections.emptyList(), ExecutableMode.INTROSPECT));
|
||||
assertThatInvocationDoesNotMatch(InstrumentedMethod.CONSTRUCTOR_NEWINSTANCE, invocation);
|
||||
}
|
||||
|
||||
|
@ -285,7 +285,7 @@ class InstrumentedMethodTests {
|
|||
void classGetDeclaredMethodShouldMatchIntrospectMethodHint() {
|
||||
List<TypeReference> parameterTypes = TypeReference.listOf(int.class, float.class);
|
||||
hints.reflection().registerType(String.class, typeHint ->
|
||||
typeHint.withMethod("scale", parameterTypes, methodHint -> methodHint.withMode(ExecutableMode.INTROSPECT)));
|
||||
typeHint.withMethod("scale", parameterTypes, ExecutableMode.INTROSPECT));
|
||||
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDMETHOD, this.stringGetScaleMethod);
|
||||
}
|
||||
|
||||
|
@ -293,7 +293,7 @@ class InstrumentedMethodTests {
|
|||
void classGetDeclaredMethodShouldMatchInvokeMethodHint() {
|
||||
List<TypeReference> parameterTypes = TypeReference.listOf(int.class, float.class);
|
||||
hints.reflection().registerType(String.class, typeHint ->
|
||||
typeHint.withMethod("scale", parameterTypes, methodHint -> methodHint.withMode(ExecutableMode.INVOKE)));
|
||||
typeHint.withMethod("scale", parameterTypes, ExecutableMode.INVOKE));
|
||||
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDMETHOD, this.stringGetScaleMethod);
|
||||
}
|
||||
|
||||
|
@ -378,14 +378,14 @@ class InstrumentedMethodTests {
|
|||
@Test
|
||||
void classGetMethodShouldMatchIntrospectMethodHint() {
|
||||
hints.reflection().registerType(String.class, typeHint ->
|
||||
typeHint.withMethod("toString", Collections.emptyList(), methodHint -> methodHint.setModes(ExecutableMode.INTROSPECT)));
|
||||
typeHint.withMethod("toString", Collections.emptyList(), ExecutableMode.INTROSPECT));
|
||||
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETMETHOD, this.stringGetToStringMethod);
|
||||
}
|
||||
|
||||
@Test
|
||||
void classGetMethodShouldMatchInvokeMethodHint() {
|
||||
hints.reflection().registerType(String.class, typeHint ->
|
||||
typeHint.withMethod("toString", Collections.emptyList(), methodHint -> methodHint.setModes(ExecutableMode.INVOKE)));
|
||||
typeHint.withMethod("toString", Collections.emptyList(), ExecutableMode.INVOKE));
|
||||
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETMETHOD, this.stringGetToStringMethod);
|
||||
}
|
||||
|
||||
|
@ -412,7 +412,7 @@ class InstrumentedMethodTests {
|
|||
RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.METHOD_INVOKE)
|
||||
.onInstance(String.class.getMethod("startsWith", String.class)).withArguments("testString", new Object[] { "test" }).build();
|
||||
hints.reflection().registerType(String.class, typeHint -> typeHint.withMethod("startsWith",
|
||||
TypeReference.listOf(String.class), methodHint -> methodHint.withMode(ExecutableMode.INVOKE)));
|
||||
TypeReference.listOf(String.class), ExecutableMode.INVOKE));
|
||||
assertThatInvocationMatches(InstrumentedMethod.METHOD_INVOKE, invocation);
|
||||
}
|
||||
|
||||
|
@ -421,7 +421,7 @@ class InstrumentedMethodTests {
|
|||
RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.METHOD_INVOKE)
|
||||
.onInstance(String.class.getMethod("toString")).withArguments("", new Object[0]).build();
|
||||
hints.reflection().registerType(String.class, typeHint ->
|
||||
typeHint.withMethod("toString", Collections.emptyList(), methodHint -> methodHint.withMode(ExecutableMode.INTROSPECT)));
|
||||
typeHint.withMethod("toString", Collections.emptyList(), ExecutableMode.INTROSPECT));
|
||||
assertThatInvocationDoesNotMatch(InstrumentedMethod.METHOD_INVOKE, invocation);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,12 +19,9 @@ package org.springframework.aot.hint;
|
|||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Executable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* A hint that describes the need for reflection on a {@link Method} or
|
||||
|
@ -37,13 +34,13 @@ public final class ExecutableHint extends MemberHint {
|
|||
|
||||
private final List<TypeReference> parameterTypes;
|
||||
|
||||
private final List<ExecutableMode> modes;
|
||||
private final ExecutableMode mode;
|
||||
|
||||
|
||||
private ExecutableHint(Builder builder) {
|
||||
super(builder.name);
|
||||
this.parameterTypes = List.copyOf(builder.parameterTypes);
|
||||
this.modes = List.copyOf(builder.modes);
|
||||
this.mode = (builder.mode != null ? builder.mode : ExecutableMode.INVOKE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,11 +72,11 @@ public final class ExecutableHint extends MemberHint {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the {@linkplain ExecutableMode modes} that apply to this hint.
|
||||
* Return the {@linkplain ExecutableMode mode} that apply to this hint.
|
||||
* @return the modes
|
||||
*/
|
||||
public List<ExecutableMode> getModes() {
|
||||
return this.modes;
|
||||
public ExecutableMode getMode() {
|
||||
return this.mode;
|
||||
}
|
||||
|
||||
|
||||
|
@ -92,7 +89,8 @@ public final class ExecutableHint extends MemberHint {
|
|||
|
||||
private final List<TypeReference> parameterTypes;
|
||||
|
||||
private final Set<ExecutableMode> modes = new LinkedHashSet<>();
|
||||
@Nullable
|
||||
private ExecutableMode mode;
|
||||
|
||||
|
||||
Builder(String name, List<TypeReference> parameterTypes) {
|
||||
|
@ -101,12 +99,14 @@ public final class ExecutableHint extends MemberHint {
|
|||
}
|
||||
|
||||
/**
|
||||
* Add the specified {@linkplain ExecutableMode mode} if necessary.
|
||||
* @param mode the mode to add
|
||||
* Specify that the {@linkplain ExecutableMode mode} is required.
|
||||
* @param mode the required mode
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
*/
|
||||
public Builder withMode(ExecutableMode mode) {
|
||||
this.modes.add(mode);
|
||||
if (this.mode == null || !this.mode.includes(mode)) {
|
||||
this.mode = mode;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -114,11 +114,15 @@ public final class ExecutableHint extends MemberHint {
|
|||
* Set the {@linkplain ExecutableMode modes} to use.
|
||||
* @param modes the mode to use
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
* @deprecated only a single mode can be set, use {@link #withMode(ExecutableMode)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public Builder setModes(ExecutableMode... modes) {
|
||||
this.modes.clear();
|
||||
if (!ObjectUtils.isEmpty(modes)) {
|
||||
this.modes.addAll(Arrays.asList(modes));
|
||||
if (modes.length > 1) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
if (modes.length == 1) {
|
||||
withMode(modes[0]);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ package org.springframework.aot.hint;
|
|||
|
||||
import java.lang.reflect.Executable;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Represent the need of reflection for a given {@link Executable}.
|
||||
*
|
||||
|
@ -37,4 +39,13 @@ public enum ExecutableMode {
|
|||
*/
|
||||
INVOKE;
|
||||
|
||||
/**
|
||||
* Specify if this mode already includes the specified {@code other} mode.
|
||||
* @param other the other mode to check
|
||||
* @return {@code true} if this mode includes the other mode
|
||||
*/
|
||||
boolean includes(@Nullable ExecutableMode other) {
|
||||
return (other == null || this.ordinal() >= other.ordinal());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ package org.springframework.aot.hint;
|
|||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* A hint that describes the need of reflection on a {@link Field}.
|
||||
*
|
||||
|
@ -33,7 +35,7 @@ public final class FieldHint extends MemberHint {
|
|||
|
||||
private FieldHint(Builder builder) {
|
||||
super(builder.name);
|
||||
this.allowWrite = builder.allowWrite;
|
||||
this.allowWrite = (builder.allowWrite != null) ? builder.allowWrite : true;
|
||||
this.allowUnsafeAccess = builder.allowUnsafeAccess;
|
||||
}
|
||||
|
||||
|
@ -61,7 +63,8 @@ public final class FieldHint extends MemberHint {
|
|||
|
||||
private final String name;
|
||||
|
||||
private boolean allowWrite;
|
||||
@Nullable
|
||||
private Boolean allowWrite;
|
||||
|
||||
private boolean allowUnsafeAccess;
|
||||
|
||||
|
|
|
@ -158,6 +158,17 @@ public class ReflectionHints {
|
|||
typeHint -> typeHint.withConstructor(mapParameters(constructor), constructorHint));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the need for reflection on the specified {@link Constructor},
|
||||
* using the specified {@link ExecutableMode}.
|
||||
* @param constructor the constructor that requires reflection
|
||||
* @param mode the requested mode
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
*/
|
||||
public ReflectionHints registerConstructor(Constructor<?> constructor, ExecutableMode mode) {
|
||||
return registerConstructor(constructor, constructorHint -> constructorHint.withMode(mode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the need for reflection on the specified {@link Constructor},
|
||||
* enabling {@link ExecutableMode#INVOKE}.
|
||||
|
@ -165,8 +176,7 @@ public class ReflectionHints {
|
|||
* @return {@code this}, to facilitate method chaining
|
||||
*/
|
||||
public ReflectionHints registerConstructor(Constructor<?> constructor) {
|
||||
return registerConstructor(constructor, constructorHint ->
|
||||
constructorHint.withMode(ExecutableMode.INVOKE));
|
||||
return registerConstructor(constructor, ExecutableMode.INVOKE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -180,6 +190,17 @@ public class ReflectionHints {
|
|||
typeHint -> typeHint.withMethod(method.getName(), mapParameters(method), methodHint));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the need for reflection on the specified {@link Method},
|
||||
* using the specified {@link ExecutableMode}.
|
||||
* @param method the method that requires reflection
|
||||
* @param mode the requested mode
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
*/
|
||||
public ReflectionHints registerMethod(Method method, ExecutableMode mode) {
|
||||
return registerMethod(method, methodHint -> methodHint.withMode(mode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the need for reflection on the specified {@link Method},
|
||||
* enabling {@link ExecutableMode#INVOKE}.
|
||||
|
@ -187,7 +208,7 @@ public class ReflectionHints {
|
|||
* @return {@code this}, to facilitate method chaining
|
||||
*/
|
||||
public ReflectionHints registerMethod(Method method) {
|
||||
return registerMethod(method, methodHint -> methodHint.withMode(ExecutableMode.INVOKE));
|
||||
return registerMethod(method, ExecutableMode.INVOKE);
|
||||
}
|
||||
|
||||
private List<TypeReference> mapParameters(Executable executable) {
|
||||
|
|
|
@ -173,6 +173,16 @@ public final class TypeHint implements ConditionalHint {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the need for reflection on the field with the specified name,
|
||||
* enabling write access.
|
||||
* @param name the name of the field
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
*/
|
||||
public Builder withField(String name) {
|
||||
return withField(name, fieldHint -> {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the need for reflection on the constructor with the specified
|
||||
* parameter types.
|
||||
|
@ -189,6 +199,27 @@ public final class TypeHint implements ConditionalHint {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the need for reflection on the constructor with the specified
|
||||
* parameter types, using the specified {@link ExecutableMode}.
|
||||
* @param parameterTypes the parameter types of the constructor
|
||||
* @param mode the requested mode
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
*/
|
||||
public Builder withConstructor(List<TypeReference> parameterTypes, ExecutableMode mode) {
|
||||
return withConstructor(parameterTypes, constructorHint -> constructorHint.withMode(mode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the need for reflection on the constructor with the specified
|
||||
* parameter types, enabling {@link ExecutableMode#INVOKE}.
|
||||
* @param parameterTypes the parameter types of the constructor
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
*/
|
||||
public Builder withConstructor(List<TypeReference> parameterTypes) {
|
||||
return withConstructor(parameterTypes, ExecutableMode.INVOKE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the need for reflection on the method with the specified name
|
||||
* and parameter types.
|
||||
|
@ -205,6 +236,29 @@ public final class TypeHint implements ConditionalHint {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the need for reflection on the method with the specified name
|
||||
* and parameter types, using the specified {@link ExecutableMode}.
|
||||
* @param name the name of the method
|
||||
* @param parameterTypes the parameter types of the constructor
|
||||
* @param mode the requested mode
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
*/
|
||||
public Builder withMethod(String name, List<TypeReference> parameterTypes, ExecutableMode mode) {
|
||||
return withMethod(name, parameterTypes, methodHint -> methodHint.withMode(mode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the need for reflection on the method with the specified name
|
||||
* and parameter types, enabling {@link ExecutableMode#INVOKE}.
|
||||
* @param name the name of the method
|
||||
* @param parameterTypes the parameter types of the constructor
|
||||
* @return {@code this}, to facilitate method chaining
|
||||
*/
|
||||
public Builder withMethod(String name, List<TypeReference> parameterTypes) {
|
||||
return withMethod(name, parameterTypes, ExecutableMode.INVOKE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified {@linkplain MemberCategory member categories}.
|
||||
* @param memberCategories the categories to apply
|
||||
|
|
|
@ -20,10 +20,7 @@ import java.lang.reflect.AnnotatedElement;
|
|||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.springframework.aot.hint.ExecutableHint.Builder;
|
||||
import org.springframework.aot.hint.ExecutableMode;
|
||||
import org.springframework.aot.hint.ReflectionHints;
|
||||
|
||||
/**
|
||||
|
@ -36,8 +33,6 @@ import org.springframework.aot.hint.ReflectionHints;
|
|||
*/
|
||||
public class SimpleReflectiveProcessor implements ReflectiveProcessor {
|
||||
|
||||
private static final Consumer<Builder> INVOKE_EXECUTABLE = hint -> hint.setModes(ExecutableMode.INVOKE);
|
||||
|
||||
@Override
|
||||
public void registerReflectionHints(ReflectionHints hints, AnnotatedElement element) {
|
||||
if (element instanceof Class<?> type) {
|
||||
|
@ -69,7 +64,7 @@ public class SimpleReflectiveProcessor implements ReflectiveProcessor {
|
|||
* @param constructor the constructor to process
|
||||
*/
|
||||
protected void registerConstructorHint(ReflectionHints hints, Constructor<?> constructor) {
|
||||
hints.registerConstructor(constructor, INVOKE_EXECUTABLE);
|
||||
hints.registerConstructor(constructor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,7 +82,7 @@ public class SimpleReflectiveProcessor implements ReflectiveProcessor {
|
|||
* @param method the method to process
|
||||
*/
|
||||
protected void registerMethodHint(ReflectionHints hints, Method method) {
|
||||
hints.registerMethod(method, INVOKE_EXECUTABLE);
|
||||
hints.registerMethod(method);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -263,11 +263,11 @@ public class ReflectionHintsPredicates {
|
|||
* and the configured {@code ExecutableMode} is compatibe
|
||||
*/
|
||||
static boolean includes(ExecutableHint hint, String name,
|
||||
List<TypeReference> parameterTypes, List<ExecutableMode> executableModes) {
|
||||
List<TypeReference> parameterTypes, ExecutableMode executableModes) {
|
||||
return hint.getName().equals(name)
|
||||
&& hint.getParameterTypes().equals(parameterTypes)
|
||||
&& (hint.getModes().contains(ExecutableMode.INVOKE)
|
||||
|| !executableModes.contains(ExecutableMode.INVOKE));
|
||||
&& (hint.getMode().equals(ExecutableMode.INVOKE)
|
||||
|| !executableModes.equals(ExecutableMode.INVOKE));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -302,7 +302,7 @@ public class ReflectionHintsPredicates {
|
|||
List<TypeReference> parameters = Arrays.stream(this.executable.getParameterTypes())
|
||||
.map(TypeReference::of).toList();
|
||||
return includes(executableHint, "<init>",
|
||||
parameters, List.of(this.executableMode));
|
||||
parameters, this.executableMode);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -341,7 +341,7 @@ public class ReflectionHintsPredicates {
|
|||
List<TypeReference> parameters = Arrays.stream(this.executable.getParameterTypes())
|
||||
.map(TypeReference::of).toList();
|
||||
return includes(executableHint, this.executable.getName(),
|
||||
parameters, List.of(this.executableMode));
|
||||
parameters, this.executableMode);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -85,10 +85,10 @@ class ReflectionHintsWriter {
|
|||
|
||||
private void handleExecutables(Map<String, Object> attributes, List<ExecutableHint> hints) {
|
||||
addIfNotEmpty(attributes, "methods", hints.stream()
|
||||
.filter(h -> h.getModes().contains(ExecutableMode.INVOKE) || h.getModes().isEmpty())
|
||||
.filter(h -> h.getMode().equals(ExecutableMode.INVOKE))
|
||||
.map(this::toAttributes).toList());
|
||||
addIfNotEmpty(attributes, "queriedMethods", hints.stream()
|
||||
.filter(h -> h.getModes().contains(ExecutableMode.INTROSPECT))
|
||||
.filter(h -> h.getMode().equals(ExecutableMode.INTROSPECT))
|
||||
.map(this::toAttributes).toList());
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright 2002-2022 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.aot.hint;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ExecutableMode}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class ExecutableModeTests {
|
||||
|
||||
@Test
|
||||
void invokeIncludesNullMode() {
|
||||
assertThat(ExecutableMode.INVOKE.includes(null)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void invokeIncludesIntrospect() {
|
||||
assertThat(ExecutableMode.INVOKE.includes(ExecutableMode.INTROSPECT)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void invokeIncludesIncludes() {
|
||||
assertThat(ExecutableMode.INVOKE.includes(ExecutableMode.INVOKE)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void introspectIncludesNullMode() {
|
||||
assertThat(ExecutableMode.INTROSPECT.includes(null)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void introspectIncludesIntrospect() {
|
||||
assertThat(ExecutableMode.INTROSPECT.includes(ExecutableMode.INTROSPECT)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void introspectDoesNotIncludeInvoke() {
|
||||
assertThat(ExecutableMode.INTROSPECT.includes(ExecutableMode.INVOKE)).isFalse();
|
||||
}
|
||||
|
||||
}
|
|
@ -121,14 +121,46 @@ class ReflectionHintsTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void registerField() {
|
||||
void registerFieldAllowsWriteByDefault() {
|
||||
Field field = ReflectionUtils.findField(TestType.class, "field");
|
||||
assertThat(field).isNotNull();
|
||||
this.reflectionHints.registerField(field);
|
||||
assertTestTypeFieldHint(fieldHint -> {
|
||||
assertThat(fieldHint.getName()).isEqualTo("field");
|
||||
assertThat(fieldHint.isAllowWrite()).isTrue();
|
||||
assertThat(fieldHint.isAllowUnsafeAccess()).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void registerFieldWithEmptyCustomizerAppliesConsistentDefault() {
|
||||
Field field = ReflectionUtils.findField(TestType.class, "field");
|
||||
assertThat(field).isNotNull();
|
||||
this.reflectionHints.registerField(field, fieldHint -> {});
|
||||
assertTestTypeFieldHint(fieldHint -> {
|
||||
assertThat(fieldHint.getName()).isEqualTo("field");
|
||||
assertThat(fieldHint.isAllowWrite()).isTrue();
|
||||
assertThat(fieldHint.isAllowUnsafeAccess()).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void registerFieldWithCustomizerAppliesCustomization() {
|
||||
Field field = ReflectionUtils.findField(TestType.class, "field");
|
||||
assertThat(field).isNotNull();
|
||||
this.reflectionHints.registerField(field, fieldHint ->
|
||||
fieldHint.allowWrite(false).allowUnsafeAccess(true));
|
||||
assertTestTypeFieldHint(fieldHint -> {
|
||||
assertThat(fieldHint.getName()).isEqualTo("field");
|
||||
assertThat(fieldHint.isAllowWrite()).isFalse();
|
||||
assertThat(fieldHint.isAllowUnsafeAccess()).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
private void assertTestTypeFieldHint(Consumer<FieldHint> fieldHint) {
|
||||
assertThat(this.reflectionHints.typeHints()).singleElement().satisfies(typeHint -> {
|
||||
assertThat(typeHint.getType().getCanonicalName()).isEqualTo(TestType.class.getCanonicalName());
|
||||
assertThat(typeHint.fields()).singleElement().satisfies(fieldHint ->
|
||||
assertThat(fieldHint.getName()).isEqualTo("field"));
|
||||
assertThat(typeHint.fields()).singleElement().satisfies(fieldHint);
|
||||
assertThat(typeHint.constructors()).isEmpty();
|
||||
assertThat(typeHint.methods()).isEmpty();
|
||||
assertThat(typeHint.getMemberCategories()).isEmpty();
|
||||
|
@ -138,14 +170,48 @@ 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 -> {
|
||||
assertThat(constructorHint.getParameterTypes()).isEmpty();
|
||||
assertThat(constructorHint.getMode()).isEqualTo(ExecutableMode.INTROSPECT);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void registerConstructorWithEmptyCustomizerAppliesConsistentDefault() {
|
||||
this.reflectionHints.registerConstructor(TestType.class.getDeclaredConstructors()[0],
|
||||
constructorHint -> {});
|
||||
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();
|
||||
assertThat(typeHint.getType().getCanonicalName()).isEqualTo(TestType.class.getCanonicalName());
|
||||
assertThat(typeHint.fields()).isEmpty();
|
||||
assertThat(typeHint.constructors()).singleElement().satisfies(constructorHint -> {
|
||||
assertThat(constructorHint.getParameterTypes()).isEmpty();
|
||||
assertThat(constructorHint.getModes()).containsOnly(ExecutableMode.INVOKE);
|
||||
});
|
||||
assertThat(typeHint.constructors()).singleElement().satisfies(constructorHint);
|
||||
assertThat(typeHint.methods()).isEmpty();
|
||||
assertThat(typeHint.getMemberCategories()).isEmpty();
|
||||
});
|
||||
|
@ -156,15 +222,56 @@ class ReflectionHintsTests {
|
|||
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);
|
||||
assertTestTypeMethodHints(methodHint -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("setName");
|
||||
assertThat(methodHint.getParameterTypes()).containsOnly(TypeReference.of(String.class));
|
||||
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INTROSPECT);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void registerMethodWithEmptyCustomizerAppliesConsistentDefault() {
|
||||
Method method = ReflectionUtils.findMethod(TestType.class, "setName", String.class);
|
||||
assertThat(method).isNotNull();
|
||||
this.reflectionHints.registerMethod(method, methodHint -> {});
|
||||
assertTestTypeMethodHints(methodHint -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("setName");
|
||||
assertThat(methodHint.getParameterTypes()).containsOnly(TypeReference.of(String.class));
|
||||
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
});
|
||||
}
|
||||
|
||||
@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());
|
||||
assertThat(typeHint.fields()).isEmpty();
|
||||
assertThat(typeHint.constructors()).isEmpty();
|
||||
assertThat(typeHint.methods()).singleElement().satisfies(methodHint -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("setName");
|
||||
assertThat(methodHint.getParameterTypes()).containsOnly(TypeReference.of(String.class));
|
||||
assertThat(methodHint.getModes()).containsOnly(ExecutableMode.INVOKE);
|
||||
});
|
||||
assertThat(typeHint.methods()).singleElement().satisfies(methodHint);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.aot.hint;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@ -54,16 +55,38 @@ class TypeHintTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void createWithField() {
|
||||
TypeHint hint = TypeHint.of(TypeReference.of(String.class))
|
||||
.withField("value", fieldHint -> fieldHint.allowWrite(true)).build();
|
||||
assertThat(hint.fields()).singleElement().satisfies(fieldHint -> {
|
||||
void createWithFieldAllowsWriteByDefault() {
|
||||
assertFieldHint(TypeHint.of(TypeReference.of(String.class))
|
||||
.withField("value"), fieldHint -> {
|
||||
assertThat(fieldHint.getName()).isEqualTo("value");
|
||||
assertThat(fieldHint.isAllowWrite()).isTrue();
|
||||
assertThat(fieldHint.isAllowUnsafeAccess()).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWithFieldAndEmptyCustomizerAppliesConsistentDefault() {
|
||||
assertFieldHint(TypeHint.of(TypeReference.of(String.class))
|
||||
.withField("value", fieldHint -> {}), fieldHint -> {
|
||||
assertThat(fieldHint.getName()).isEqualTo("value");
|
||||
assertThat(fieldHint.isAllowWrite()).isTrue();
|
||||
assertThat(fieldHint.isAllowUnsafeAccess()).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWithFieldAndCustomizerAppliesCustomization() {
|
||||
assertFieldHint(TypeHint.of(TypeReference.of(String.class))
|
||||
.withField("value", fieldHint -> {
|
||||
fieldHint.allowWrite(false);
|
||||
fieldHint.allowUnsafeAccess(true);
|
||||
}), fieldHint -> {
|
||||
assertThat(fieldHint.getName()).isEqualTo("value");
|
||||
assertThat(fieldHint.isAllowWrite()).isFalse();
|
||||
assertThat(fieldHint.isAllowUnsafeAccess()).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWithFieldReuseBuilder() {
|
||||
Builder builder = TypeHint.of(TypeReference.of(String.class));
|
||||
|
@ -72,64 +95,175 @@ class TypeHintTests {
|
|||
fieldHint.allowWrite(true);
|
||||
fieldHint.allowUnsafeAccess(false);
|
||||
});
|
||||
TypeHint hint = builder.build();
|
||||
assertThat(hint.fields()).singleElement().satisfies(fieldHint -> {
|
||||
assertFieldHint(builder, fieldHint -> {
|
||||
assertThat(fieldHint.getName()).isEqualTo("value");
|
||||
assertThat(fieldHint.isAllowWrite()).isTrue();
|
||||
assertThat(fieldHint.isAllowUnsafeAccess()).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
void assertFieldHint(Builder builder, Consumer<FieldHint> fieldHint) {
|
||||
TypeHint hint = builder.build();
|
||||
assertThat(hint.fields()).singleElement().satisfies(fieldHint);
|
||||
assertThat(hint.constructors()).isEmpty();
|
||||
assertThat(hint.methods()).isEmpty();
|
||||
assertThat(hint.getMemberCategories()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWithConstructor() {
|
||||
List<TypeReference> parameterTypes = TypeReference.listOf(byte[].class, int.class);
|
||||
TypeHint hint = TypeHint.of(TypeReference.of(String.class)).withConstructor(parameterTypes,
|
||||
constructorHint -> constructorHint.withMode(ExecutableMode.INVOKE)).build();
|
||||
assertThat(hint.constructors()).singleElement().satisfies(constructorHint -> {
|
||||
assertConstructorHint(TypeHint.of(TypeReference.of(String.class))
|
||||
.withConstructor(parameterTypes), constructorHint -> {
|
||||
assertThat(constructorHint.getParameterTypes()).containsOnlyOnceElementsOf(parameterTypes);
|
||||
assertThat(constructorHint.getModes()).containsOnly(ExecutableMode.INVOKE);
|
||||
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 -> {
|
||||
assertThat(constructorHint.getParameterTypes()).containsOnlyOnceElementsOf(parameterTypes);
|
||||
assertThat(constructorHint.getMode()).isEqualTo(ExecutableMode.INTROSPECT);
|
||||
});
|
||||
}
|
||||
|
||||
@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() {
|
||||
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 -> {
|
||||
assertThat(constructorHint.getParameterTypes()).containsExactlyElementsOf(parameterTypes);
|
||||
assertThat(constructorHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void createConstructorReuseBuilderAndApplyExecutableModePrecedence() {
|
||||
List<TypeReference> parameterTypes = TypeReference.listOf(byte[].class, int.class);
|
||||
Builder builder = TypeHint.of(TypeReference.of(String.class)).withConstructor(parameterTypes,
|
||||
constructorHint -> constructorHint.withMode(ExecutableMode.INVOKE));
|
||||
TypeHint hint = builder.withConstructor(parameterTypes, constructorHint ->
|
||||
constructorHint.withMode(ExecutableMode.INTROSPECT)).build();
|
||||
assertThat(hint.constructors()).singleElement().satisfies(constructorHint -> {
|
||||
assertConstructorHint(builder.withConstructor(parameterTypes, constructorHint ->
|
||||
constructorHint.withMode(ExecutableMode.INTROSPECT)), constructorHint -> {
|
||||
assertThat(constructorHint.getParameterTypes()).containsExactlyElementsOf(parameterTypes);
|
||||
assertThat(constructorHint.getModes()).containsOnly(ExecutableMode.INVOKE, ExecutableMode.INTROSPECT);
|
||||
assertThat(constructorHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
});
|
||||
}
|
||||
|
||||
void assertConstructorHint(Builder builder, Consumer<ExecutableHint> constructorHint) {
|
||||
TypeHint hint = builder.build();
|
||||
assertThat(hint.fields()).isEmpty();
|
||||
assertThat(hint.constructors()).singleElement().satisfies(constructorHint);
|
||||
assertThat(hint.methods()).isEmpty();
|
||||
assertThat(hint.getMemberCategories()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWithMethod() {
|
||||
List<TypeReference> parameterTypes = List.of(TypeReference.of(char[].class));
|
||||
TypeHint hint = TypeHint.of(TypeReference.of(String.class)).withMethod("valueOf", parameterTypes,
|
||||
methodHint -> methodHint.withMode(ExecutableMode.INVOKE)).build();
|
||||
assertThat(hint.methods()).singleElement().satisfies(methodHint -> {
|
||||
assertMethodHint(TypeHint.of(TypeReference.of(String.class))
|
||||
.withMethod("valueOf", parameterTypes), methodHint -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("valueOf");
|
||||
assertThat(methodHint.getParameterTypes()).containsExactlyElementsOf(parameterTypes);
|
||||
assertThat(methodHint.getModes()).containsOnly(ExecutableMode.INVOKE);
|
||||
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWithMethodReuseBuilder() {
|
||||
List<TypeReference> parameterTypes = TypeReference.listOf(char[].class);
|
||||
Builder builder = TypeHint.of(TypeReference.of(String.class)).withMethod("valueOf", parameterTypes,
|
||||
methodHint -> methodHint.withMode(ExecutableMode.INVOKE));
|
||||
TypeHint hint = builder.withMethod("valueOf", parameterTypes,
|
||||
methodHint -> methodHint.setModes(ExecutableMode.INTROSPECT)).build();
|
||||
assertThat(hint.methods()).singleElement().satisfies(methodHint -> {
|
||||
void createWithMethodAndMode() {
|
||||
List<TypeReference> parameterTypes = List.of(TypeReference.of(char[].class));
|
||||
assertMethodHint(TypeHint.of(TypeReference.of(String.class))
|
||||
.withMethod("valueOf", parameterTypes, ExecutableMode.INTROSPECT), methodHint -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("valueOf");
|
||||
assertThat(methodHint.getParameterTypes()).containsExactlyElementsOf(parameterTypes);
|
||||
assertThat(methodHint.getModes()).containsOnly(ExecutableMode.INTROSPECT);
|
||||
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INTROSPECT);
|
||||
});
|
||||
}
|
||||
|
||||
@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() {
|
||||
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 -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("valueOf");
|
||||
assertThat(methodHint.getParameterTypes()).containsExactlyElementsOf(parameterTypes);
|
||||
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWithMethodReuseBuilderAndApplyExecutableModePrecedence() {
|
||||
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 -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("valueOf");
|
||||
assertThat(methodHint.getParameterTypes()).containsExactlyElementsOf(parameterTypes);
|
||||
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
});
|
||||
}
|
||||
|
||||
void assertMethodHint(Builder builder, Consumer<ExecutableHint> methodHint) {
|
||||
TypeHint hint = builder.build();
|
||||
assertThat(hint.fields()).isEmpty();
|
||||
assertThat(hint.constructors()).isEmpty();
|
||||
assertThat(hint.methods()).singleElement().satisfies(methodHint);
|
||||
assertThat(hint.getMemberCategories()).isEmpty();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void createWithMemberCategory() {
|
||||
TypeHint hint = TypeHint.of(TypeReference.of(String.class))
|
||||
|
|
|
@ -60,7 +60,7 @@ class SimpleReflectiveProcessorTests {
|
|||
assertThat(typeHint.getMemberCategories()).isEmpty();
|
||||
assertThat(typeHint.constructors()).singleElement().satisfies(constructorHint -> {
|
||||
assertThat(constructorHint.getName()).isEqualTo("<init>");
|
||||
assertThat(constructorHint.getModes()).containsExactly(ExecutableMode.INVOKE);
|
||||
assertThat(constructorHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
assertThat(constructorHint.getParameterTypes()).containsExactly(TypeReference.of(String.class));
|
||||
});
|
||||
assertThat(typeHint.fields()).isEmpty();
|
||||
|
@ -93,7 +93,7 @@ class SimpleReflectiveProcessorTests {
|
|||
assertThat(typeHint.fields()).isEmpty();
|
||||
assertThat(typeHint.methods()).singleElement().satisfies(methodHint -> {
|
||||
assertThat(methodHint.getName()).isEqualTo("setName");
|
||||
assertThat(methodHint.getModes()).containsExactly(ExecutableMode.INVOKE);
|
||||
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
|
||||
assertThat(methodHint.getParameterTypes()).containsExactly(TypeReference.of(String.class));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -157,7 +157,7 @@ class ReflectionHintsPredicatesTests {
|
|||
@Test
|
||||
void constructorIntrospectionMatchesConstructorHint() {
|
||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint ->
|
||||
typeHint.withConstructor(Collections.emptyList(), constructorHint -> {}));
|
||||
typeHint.withConstructor(Collections.emptyList(), ExecutableMode.INTROSPECT));
|
||||
assertPredicateMatches(reflection.onConstructor(publicConstructor).introspect());
|
||||
}
|
||||
|
||||
|
@ -192,15 +192,14 @@ class ReflectionHintsPredicatesTests {
|
|||
@Test
|
||||
void constructorInvocationDoesNotMatchConstructorHint() {
|
||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.
|
||||
withConstructor(Collections.emptyList(), constructorHint -> {}));
|
||||
withConstructor(Collections.emptyList(), ExecutableMode.INTROSPECT));
|
||||
assertPredicateDoesNotMatch(reflection.onConstructor(publicConstructor).invoke());
|
||||
}
|
||||
|
||||
@Test
|
||||
void constructorInvocationMatchesConstructorInvocationHint() {
|
||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.
|
||||
withConstructor(Collections.emptyList(), constructorHint ->
|
||||
constructorHint.withMode(ExecutableMode.INVOKE)));
|
||||
withConstructor(Collections.emptyList(), ExecutableMode.INVOKE));
|
||||
assertPredicateMatches(reflection.onConstructor(publicConstructor).invoke());
|
||||
}
|
||||
|
||||
|
@ -235,7 +234,7 @@ class ReflectionHintsPredicatesTests {
|
|||
@Test
|
||||
void privateConstructorIntrospectionMatchesConstructorHint() {
|
||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint ->
|
||||
typeHint.withConstructor(TypeReference.listOf(String.class), constructorHint -> {}));
|
||||
typeHint.withConstructor(TypeReference.listOf(String.class), ExecutableMode.INTROSPECT));
|
||||
assertPredicateMatches(reflection.onConstructor(privateConstructor).introspect());
|
||||
}
|
||||
|
||||
|
@ -270,15 +269,14 @@ class ReflectionHintsPredicatesTests {
|
|||
@Test
|
||||
void privateConstructorInvocationDoesNotMatchConstructorHint() {
|
||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint ->
|
||||
typeHint.withConstructor(TypeReference.listOf(String.class), constructorHint -> {}));
|
||||
typeHint.withConstructor(TypeReference.listOf(String.class), ExecutableMode.INTROSPECT));
|
||||
assertPredicateDoesNotMatch(reflection.onConstructor(privateConstructor).invoke());
|
||||
}
|
||||
|
||||
@Test
|
||||
void privateConstructorInvocationMatchesConstructorInvocationHint() {
|
||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint ->
|
||||
typeHint.withConstructor(TypeReference.listOf(String.class),
|
||||
constructorHint -> constructorHint.withMode(ExecutableMode.INVOKE)));
|
||||
typeHint.withConstructor(TypeReference.listOf(String.class), ExecutableMode.INVOKE));
|
||||
assertPredicateMatches(reflection.onConstructor(privateConstructor).invoke());
|
||||
}
|
||||
|
||||
|
@ -317,8 +315,8 @@ class ReflectionHintsPredicatesTests {
|
|||
|
||||
@Test
|
||||
void methodIntrospectionMatchesMethodHint() {
|
||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withMethod("publicMethod", Collections.emptyList(), methodHint -> {
|
||||
}));
|
||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint ->
|
||||
typeHint.withMethod("publicMethod", Collections.emptyList(), ExecutableMode.INTROSPECT));
|
||||
assertPredicateMatches(reflection.onMethod(SampleClass.class, "publicMethod").introspect());
|
||||
}
|
||||
|
||||
|
@ -348,14 +346,15 @@ class ReflectionHintsPredicatesTests {
|
|||
|
||||
@Test
|
||||
void methodInvocationDoesNotMatchMethodHint() {
|
||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withMethod("publicMethod", Collections.emptyList(), methodHint -> {
|
||||
}));
|
||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint ->
|
||||
typeHint.withMethod("publicMethod", Collections.emptyList(), ExecutableMode.INTROSPECT));
|
||||
assertPredicateDoesNotMatch(reflection.onMethod(SampleClass.class, "publicMethod").invoke());
|
||||
}
|
||||
|
||||
@Test
|
||||
void methodInvocationMatchesMethodInvocationHint() {
|
||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withMethod("publicMethod", Collections.emptyList(), methodHint -> methodHint.withMode(ExecutableMode.INVOKE)));
|
||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint ->
|
||||
typeHint.withMethod("publicMethod", Collections.emptyList(), ExecutableMode.INVOKE));
|
||||
assertPredicateMatches(reflection.onMethod(SampleClass.class, "publicMethod").invoke());
|
||||
}
|
||||
|
||||
|
@ -385,8 +384,8 @@ class ReflectionHintsPredicatesTests {
|
|||
|
||||
@Test
|
||||
void privateMethodIntrospectionMatchesMethodHint() {
|
||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withMethod("privateMethod", Collections.emptyList(), methodHint -> {
|
||||
}));
|
||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint ->
|
||||
typeHint.withMethod("privateMethod", Collections.emptyList(), ExecutableMode.INTROSPECT));
|
||||
assertPredicateMatches(reflection.onMethod(SampleClass.class, "privateMethod").introspect());
|
||||
}
|
||||
|
||||
|
@ -416,14 +415,15 @@ class ReflectionHintsPredicatesTests {
|
|||
|
||||
@Test
|
||||
void privateMethodInvocationDoesNotMatchMethodHint() {
|
||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withMethod("privateMethod", Collections.emptyList(), methodHint -> {
|
||||
}));
|
||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint ->
|
||||
typeHint.withMethod("privateMethod", Collections.emptyList(), ExecutableMode.INTROSPECT));
|
||||
assertPredicateDoesNotMatch(reflection.onMethod(SampleClass.class, "privateMethod").invoke());
|
||||
}
|
||||
|
||||
@Test
|
||||
void privateMethodInvocationMatchesMethodInvocationHint() {
|
||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withMethod("privateMethod", Collections.emptyList(), methodHint -> methodHint.withMode(ExecutableMode.INVOKE)));
|
||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint ->
|
||||
typeHint.withMethod("privateMethod", Collections.emptyList(), ExecutableMode.INVOKE));
|
||||
assertPredicateMatches(reflection.onMethod(SampleClass.class, "privateMethod").invoke());
|
||||
}
|
||||
|
||||
|
@ -470,8 +470,8 @@ class ReflectionHintsPredicatesTests {
|
|||
|
||||
@Test
|
||||
void fieldWriteReflectionDoesNotMatchFieldHint() {
|
||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withField("publicField", fieldHint -> {
|
||||
}));
|
||||
runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withField("publicField",
|
||||
fieldHint -> fieldHint.allowWrite(false)));
|
||||
assertPredicateDoesNotMatch(reflection.onField(SampleClass.class, "publicField").allowWrite());
|
||||
}
|
||||
|
||||
|
|
|
@ -106,16 +106,14 @@ public class FileNativeConfigurationWriterTests {
|
|||
MemberCategory.INTROSPECT_PUBLIC_METHODS, MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.PUBLIC_CLASSES, MemberCategory.DECLARED_CLASSES)
|
||||
.withField("DEFAULT_CHARSET", fieldBuilder -> {})
|
||||
.withField("DEFAULT_CHARSET", fieldBuilder -> fieldBuilder.allowWrite(false))
|
||||
.withField("defaultCharset", fieldBuilder -> {
|
||||
fieldBuilder.allowWrite(true);
|
||||
fieldBuilder.allowUnsafeAccess(true);
|
||||
})
|
||||
.withConstructor(TypeReference.listOf(List.class, boolean.class, MimeType.class), constructorHint ->
|
||||
constructorHint.withMode(ExecutableMode.INTROSPECT))
|
||||
.withMethod("setDefaultCharset", TypeReference.listOf(Charset.class), ctorBuilder -> {})
|
||||
.withMethod("getDefaultCharset", Collections.emptyList(), constructorHint ->
|
||||
constructorHint.withMode(ExecutableMode.INTROSPECT));
|
||||
.withConstructor(TypeReference.listOf(List.class, boolean.class, MimeType.class), ExecutableMode.INTROSPECT)
|
||||
.withMethod("setDefaultCharset", TypeReference.listOf(Charset.class))
|
||||
.withMethod("getDefaultCharset", Collections.emptyList(), ExecutableMode.INTROSPECT);
|
||||
});
|
||||
generator.write(hints);
|
||||
assertEquals("""
|
||||
|
|
|
@ -49,26 +49,22 @@ public class ReflectionHintsWriterTests {
|
|||
@Test
|
||||
void one() throws JSONException {
|
||||
ReflectionHints hints = new ReflectionHints();
|
||||
hints.registerType(StringDecoder.class, builder -> {
|
||||
builder
|
||||
.onReachableType(TypeReference.of(String.class))
|
||||
.withMembers(MemberCategory.PUBLIC_FIELDS, MemberCategory.DECLARED_FIELDS,
|
||||
MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS, MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS,
|
||||
MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
|
||||
MemberCategory.INTROSPECT_PUBLIC_METHODS, MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.PUBLIC_CLASSES, MemberCategory.DECLARED_CLASSES)
|
||||
.withField("DEFAULT_CHARSET", fieldBuilder -> {})
|
||||
.withField("defaultCharset", fieldBuilder -> {
|
||||
fieldBuilder.allowWrite(true);
|
||||
fieldBuilder.allowUnsafeAccess(true);
|
||||
})
|
||||
.withConstructor(TypeReference.listOf(List.class, boolean.class, MimeType.class), constructorHint ->
|
||||
constructorHint.withMode(ExecutableMode.INTROSPECT))
|
||||
.withMethod("setDefaultCharset", List.of(TypeReference.of(Charset.class)), ctorBuilder -> {})
|
||||
.withMethod("getDefaultCharset", Collections.emptyList(), constructorHint ->
|
||||
constructorHint.withMode(ExecutableMode.INTROSPECT));
|
||||
});
|
||||
hints.registerType(StringDecoder.class, builder -> builder
|
||||
.onReachableType(TypeReference.of(String.class))
|
||||
.withMembers(MemberCategory.PUBLIC_FIELDS, MemberCategory.DECLARED_FIELDS,
|
||||
MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS, MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS,
|
||||
MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
|
||||
MemberCategory.INTROSPECT_PUBLIC_METHODS, MemberCategory.INTROSPECT_DECLARED_METHODS,
|
||||
MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_DECLARED_METHODS,
|
||||
MemberCategory.PUBLIC_CLASSES, MemberCategory.DECLARED_CLASSES)
|
||||
.withField("DEFAULT_CHARSET", fieldBuilder -> fieldBuilder.allowWrite(false))
|
||||
.withField("defaultCharset", fieldBuilder -> {
|
||||
fieldBuilder.allowWrite(true);
|
||||
fieldBuilder.allowUnsafeAccess(true);
|
||||
})
|
||||
.withConstructor(TypeReference.listOf(List.class, boolean.class, MimeType.class), ExecutableMode.INTROSPECT)
|
||||
.withMethod("setDefaultCharset", List.of(TypeReference.of(Charset.class)))
|
||||
.withMethod("getDefaultCharset", Collections.emptyList(), ExecutableMode.INTROSPECT));
|
||||
assertEquals("""
|
||||
[
|
||||
{
|
||||
|
@ -120,7 +116,7 @@ public class ReflectionHintsWriterTests {
|
|||
void queriedMethods() throws JSONException {
|
||||
ReflectionHints hints = new ReflectionHints();
|
||||
hints.registerType(Integer.class, builder -> builder.withMethod("parseInt",
|
||||
TypeReference.listOf(String.class), b -> b.withMode(ExecutableMode.INTROSPECT)));
|
||||
TypeReference.listOf(String.class), ExecutableMode.INTROSPECT));
|
||||
|
||||
assertEquals("""
|
||||
[
|
||||
|
@ -141,7 +137,7 @@ public class ReflectionHintsWriterTests {
|
|||
void methods() throws JSONException {
|
||||
ReflectionHints hints = new ReflectionHints();
|
||||
hints.registerType(Integer.class, builder -> builder.withMethod("parseInt",
|
||||
TypeReference.listOf(String.class), b -> b.withMode(ExecutableMode.INVOKE)));
|
||||
TypeReference.listOf(String.class), ExecutableMode.INVOKE));
|
||||
|
||||
assertEquals("""
|
||||
[
|
||||
|
@ -162,7 +158,7 @@ public class ReflectionHintsWriterTests {
|
|||
void methodWithInnerClassParameter() throws JSONException {
|
||||
ReflectionHints hints = new ReflectionHints();
|
||||
hints.registerType(Integer.class, builder -> builder.withMethod("test",
|
||||
TypeReference.listOf(Inner.class), b -> b.withMode(ExecutableMode.INVOKE)));
|
||||
TypeReference.listOf(Inner.class), ExecutableMode.INVOKE));
|
||||
|
||||
assertEquals("""
|
||||
[
|
||||
|
@ -183,9 +179,9 @@ public class ReflectionHintsWriterTests {
|
|||
void methodAndQueriedMethods() throws JSONException {
|
||||
ReflectionHints hints = new ReflectionHints();
|
||||
hints.registerType(Integer.class, builder -> builder.withMethod("parseInt",
|
||||
TypeReference.listOf(String.class), b -> b.withMode(ExecutableMode.INVOKE)));
|
||||
TypeReference.listOf(String.class), ExecutableMode.INVOKE));
|
||||
hints.registerType(Integer.class, builder -> builder.withMethod("parseInt",
|
||||
TypeReference.listOf(String.class), b -> b.withMode(ExecutableMode.INTROSPECT)));
|
||||
TypeReference.listOf(String.class, int.class), ExecutableMode.INTROSPECT));
|
||||
|
||||
assertEquals("""
|
||||
[
|
||||
|
@ -194,7 +190,7 @@ public class ReflectionHintsWriterTests {
|
|||
"queriedMethods": [
|
||||
{
|
||||
"name": "parseInt",
|
||||
"parameterTypes": ["java.lang.String"]
|
||||
"parameterTypes": ["java.lang.String", "int"]
|
||||
}
|
||||
],
|
||||
"methods": [
|
||||
|
|
|
@ -64,13 +64,13 @@ class MessageMappingReflectiveProcessor implements ReflectiveProcessor {
|
|||
}
|
||||
|
||||
protected void registerMethodHints(ReflectionHints hints, Method method) {
|
||||
hints.registerMethod(method, hint -> hint.setModes(ExecutableMode.INVOKE));
|
||||
hints.registerMethod(method, ExecutableMode.INVOKE);
|
||||
registerParameterHints(hints, method);
|
||||
registerReturnValueHints(hints, method);
|
||||
}
|
||||
|
||||
protected void registerParameterHints(ReflectionHints hints, Method method) {
|
||||
hints.registerMethod(method, hint -> hint.setModes(ExecutableMode.INVOKE));
|
||||
hints.registerMethod(method, ExecutableMode.INVOKE);
|
||||
for (Parameter parameter : method.getParameters()) {
|
||||
MethodParameter methodParameter = MethodParameter.forParameter(parameter);
|
||||
if (Message.class.isAssignableFrom(methodParameter.getParameterType())) {
|
||||
|
|
|
@ -63,13 +63,13 @@ class RequestMappingReflectiveProcessor implements ReflectiveProcessor {
|
|||
}
|
||||
|
||||
protected void registerMethodHints(ReflectionHints hints, Method method) {
|
||||
hints.registerMethod(method, hint -> hint.setModes(ExecutableMode.INVOKE));
|
||||
hints.registerMethod(method, ExecutableMode.INVOKE);
|
||||
registerParameterHints(hints, method);
|
||||
registerReturnValueHints(hints, method);
|
||||
}
|
||||
|
||||
protected void registerParameterHints(ReflectionHints hints, Method method) {
|
||||
hints.registerMethod(method, hint -> hint.setModes(ExecutableMode.INVOKE));
|
||||
hints.registerMethod(method, ExecutableMode.INVOKE);
|
||||
for (Parameter parameter : method.getParameters()) {
|
||||
MethodParameter methodParameter = MethodParameter.forParameter(parameter);
|
||||
if (methodParameter.hasParameterAnnotation(RequestBody.class) ||
|
||||
|
|
Loading…
Reference in New Issue