Update AOT support after RuntimeHints changes

This commit adapts AOT support in various modules after the RuntimeHints
and related deprecation changes.

`MemberCategory.INTROSPECT_*` hints are now removed and
`MemberCategory.*_FIELDS` are  replaced with
`MemberCategory.INVOKE*_FIELDS` when invocation is needed.

Usage of `RuntimeHintsAgent` are also deprecated.

Closes gh-33847
This commit is contained in:
Brian Clozel 2024-11-29 14:44:05 +01:00
parent 0759129c14
commit ba312f6c7c
31 changed files with 81 additions and 111 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2024 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.
@ -24,7 +24,6 @@ import org.springframework.aot.hint.ExecutableMode;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.test.agent.EnabledIfRuntimeHintsAgent;
import org.springframework.aot.test.agent.RuntimeHintsInvocations;
import org.springframework.aot.test.agent.RuntimeHintsRecorder;
import org.springframework.core.SpringVersion;
import static org.assertj.core.api.Assertions.assertThat;
@ -33,6 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat;
// method is only enabled if the RuntimeHintsAgent is loaded on the current JVM.
// It also tags tests with the "RuntimeHints" JUnit tag.
@EnabledIfRuntimeHintsAgent
@SuppressWarnings("removal")
class SampleReflectionRuntimeHintsTests {
@Test
@ -43,7 +43,7 @@ class SampleReflectionRuntimeHintsTests {
typeHint.withMethod("getVersion", List.of(), ExecutableMode.INVOKE));
// Invoke the relevant piece of code we want to test within a recording lambda
RuntimeHintsInvocations invocations = RuntimeHintsRecorder.record(() -> {
RuntimeHintsInvocations invocations = org.springframework.aot.test.agent.RuntimeHintsRecorder.record(() -> {
SampleReflection sample = new SampleReflection();
sample.performReflection();
});

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2024 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.
@ -18,24 +18,23 @@ package org.springframework.aot.test;
import org.junit.jupiter.api.Test;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.test.agent.EnabledIfRuntimeHintsAgent;
import org.springframework.aot.test.agent.RuntimeHintsInvocations;
import org.springframework.aot.test.agent.RuntimeHintsRecorder;
import static org.assertj.core.api.Assertions.assertThat;
@EnabledIfRuntimeHintsAgent
@SuppressWarnings("removal")
class ReflectionInvocationsTests {
@Test
void sampleTest() {
RuntimeHints hints = new RuntimeHints();
hints.reflection().registerType(String.class, MemberCategory.INTROSPECT_PUBLIC_METHODS);
hints.reflection().registerType(String.class);
RuntimeHintsInvocations invocations = RuntimeHintsRecorder.record(() -> {
RuntimeHintsInvocations invocations = org.springframework.aot.test.agent.RuntimeHintsRecorder.record(() -> {
SampleReflection sample = new SampleReflection();
sample.sample(); // does Method[] methods = String.class.getMethods();
});
@ -45,9 +44,9 @@ class ReflectionInvocationsTests {
@Test
void multipleCallsTest() {
RuntimeHints hints = new RuntimeHints();
hints.reflection().registerType(String.class, MemberCategory.INTROSPECT_PUBLIC_METHODS);
hints.reflection().registerType(Integer.class,MemberCategory.INTROSPECT_PUBLIC_METHODS);
RuntimeHintsInvocations invocations = RuntimeHintsRecorder.record(() -> {
hints.reflection().registerType(String.class);
hints.reflection().registerType(Integer.class);
RuntimeHintsInvocations invocations = org.springframework.aot.test.agent.RuntimeHintsRecorder.record(() -> {
SampleReflection sample = new SampleReflection();
sample.multipleCalls(); // does Method[] methods = String.class.getMethods(); methods = Integer.class.getMethods();
});

View File

@ -74,7 +74,7 @@ class AspectJAdvisorBeanRegistrationAotProcessor implements BeanRegistrationAotP
@Override
public void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) {
generationContext.getRuntimeHints().reflection().registerType(this.beanClass, MemberCategory.DECLARED_FIELDS);
generationContext.getRuntimeHints().reflection().registerType(this.beanClass, MemberCategory.INVOKE_DECLARED_FIELDS);
}
}

View File

@ -48,7 +48,7 @@ class AspectJAdvisorBeanRegistrationAotProcessorTests {
@Test
void shouldProcessAspectJClass() {
process(AspectJClass.class);
assertThat(reflection().onType(AspectJClass.class).withMemberCategory(MemberCategory.DECLARED_FIELDS))
assertThat(reflection().onType(AspectJClass.class).withMemberCategory(MemberCategory.INVOKE_DECLARED_FIELDS))
.accepts(this.runtimeHints);
}

View File

@ -1065,7 +1065,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
}
else {
codeWarnings.detectDeprecation(method);
hints.reflection().registerMethod(method, ExecutableMode.INTROSPECT);
hints.reflection().registerType(method.getDeclaringClass());
CodeBlock arguments = new AutowiredArgumentsCodeGenerator(this.target,
method).generateCode(method.getParameterTypes());
CodeBlock injectionCode = CodeBlock.of("args -> $L.$L($L)",

View File

@ -252,10 +252,10 @@ class BeanDefinitionPropertiesCodeGenerator {
// ReflectionUtils#findField searches recursively in the type hierarchy
Class<?> searchType = beanDefinition.getTargetType();
while (searchType != null && searchType != writeMethod.getDeclaringClass()) {
this.hints.reflection().registerType(searchType, MemberCategory.DECLARED_FIELDS);
this.hints.reflection().registerType(searchType, MemberCategory.INVOKE_DECLARED_FIELDS);
searchType = searchType.getSuperclass();
}
this.hints.reflection().registerType(writeMethod.getDeclaringClass(), MemberCategory.DECLARED_FIELDS);
this.hints.reflection().registerType(writeMethod.getDeclaringClass(), MemberCategory.INVOKE_DECLARED_FIELDS);
}
private void addQualifiers(CodeBlock.Builder code, RootBeanDefinition beanDefinition) {

View File

@ -26,9 +26,9 @@ import org.springframework.aot.generate.GeneratedMethods;
import org.springframework.aot.generate.GenerationContext;
import org.springframework.aot.generate.MethodReference;
import org.springframework.aot.generate.MethodReference.ArgumentCodeGenerator;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.ReflectionHints;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.TypeHint;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RegisteredBean;
import org.springframework.javapoet.ClassName;
@ -100,8 +100,8 @@ class BeanRegistrationsAotContribution
registrations.forEach(registration -> {
ReflectionHints hints = runtimeHints.reflection();
Class<?> beanClass = registration.registeredBean.getBeanClass();
hints.registerType(beanClass, MemberCategory.INTROSPECT_PUBLIC_METHODS, MemberCategory.INTROSPECT_DECLARED_METHODS);
hints.registerForInterfaces(beanClass, typeHint -> typeHint.withMembers(MemberCategory.INTROSPECT_PUBLIC_METHODS));
hints.registerType(beanClass);
hints.registerForInterfaces(beanClass, TypeHint.Builder::withMembers);
});
}

View File

@ -172,8 +172,7 @@ public class InstanceSupplierCodeGenerator {
}
private CodeBlock generateCodeForAccessibleConstructor(String beanName, Constructor<?> constructor) {
this.generationContext.getRuntimeHints().reflection().registerConstructor(
constructor, ExecutableMode.INTROSPECT);
this.generationContext.getRuntimeHints().reflection().registerType(constructor.getDeclaringClass());
if (constructor.getParameterCount() == 0) {
if (!this.allowDirectSupplierShortcut) {
@ -265,7 +264,7 @@ public class InstanceSupplierCodeGenerator {
private CodeBlock generateCodeForAccessibleFactoryMethod(String beanName,
Method factoryMethod, Class<?> targetClass, @Nullable String factoryBeanName) {
this.generationContext.getRuntimeHints().reflection().registerMethod(factoryMethod, ExecutableMode.INTROSPECT);
this.generationContext.getRuntimeHints().reflection().registerType(factoryMethod.getDeclaringClass());
if (factoryBeanName == null && factoryMethod.getParameterCount() == 0) {
Class<?> suppliedType = ClassUtils.resolvePrimitiveIfNecessary(factoryMethod.getReturnType());

View File

@ -574,7 +574,7 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
private void assertHasDeclaredFieldsHint(Class<?> beanType) {
assertThat(RuntimeHintsPredicates.reflection()
.onType(beanType).withMemberCategory(MemberCategory.DECLARED_FIELDS))
.onType(beanType).withMemberCategory(MemberCategory.INVOKE_DECLARED_FIELDS))
.accepts(this.generationContext.getRuntimeHints());
}

View File

@ -31,7 +31,6 @@ import org.springframework.aot.generate.GenerationContext;
import org.springframework.aot.generate.MethodReference;
import org.springframework.aot.generate.MethodReference.ArgumentCodeGenerator;
import org.springframework.aot.generate.ValueCodeGenerationException;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.test.generate.TestGenerationContext;
import org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.Registration;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
@ -149,14 +148,11 @@ class BeanRegistrationsAotContributionTests {
registeredBean, null, List.of());
BeanRegistrationsAotContribution contribution = createContribution(registeredBean, generator);
contribution.applyTo(this.generationContext, this.beanFactoryInitializationCode);
assertThat(reflection().onType(Employee.class)
.withMemberCategories(MemberCategory.INTROSPECT_PUBLIC_METHODS, MemberCategory.INTROSPECT_DECLARED_METHODS))
assertThat(reflection().onType(Employee.class))
.accepts(this.generationContext.getRuntimeHints());
assertThat(reflection().onType(ITestBean.class)
.withMemberCategory(MemberCategory.INTROSPECT_PUBLIC_METHODS))
assertThat(reflection().onType(ITestBean.class))
.accepts(this.generationContext.getRuntimeHints());
assertThat(reflection().onType(AgeHolder.class)
.withMemberCategory(MemberCategory.INTROSPECT_PUBLIC_METHODS))
assertThat(reflection().onType(AgeHolder.class))
.accepts(this.generationContext.getRuntimeHints());
}

View File

@ -100,8 +100,7 @@ class InstanceSupplierCodeGeneratorTests {
assertThat(compiled.getSourceFile())
.contains("InstanceSupplier.using(TestBean::new)");
});
assertThat(getReflectionHints().getTypeHint(TestBean.class))
.satisfies(hasConstructorWithMode(ExecutableMode.INTROSPECT));
assertThat(getReflectionHints().getTypeHint(TestBean.class)).isNotNull();
}
@Test
@ -112,8 +111,7 @@ class InstanceSupplierCodeGeneratorTests {
InjectionComponent bean = getBean(beanDefinition, instanceSupplier);
assertThat(bean).isInstanceOf(InjectionComponent.class).extracting("bean").isEqualTo("injected");
});
assertThat(getReflectionHints().getTypeHint(InjectionComponent.class))
.satisfies(hasConstructorWithMode(ExecutableMode.INTROSPECT));
assertThat(getReflectionHints().getTypeHint(InjectionComponent.class)).isNotNull();
}
@Test
@ -126,8 +124,7 @@ class InstanceSupplierCodeGeneratorTests {
assertThat(compiled.getSourceFile()).contains(
"getBeanFactory().getBean(InnerComponentConfiguration.class).new NoDependencyComponent()");
});
assertThat(getReflectionHints().getTypeHint(NoDependencyComponent.class))
.satisfies(hasConstructorWithMode(ExecutableMode.INTROSPECT));
assertThat(getReflectionHints().getTypeHint(NoDependencyComponent.class)).isNotNull();
}
@Test
@ -141,8 +138,7 @@ class InstanceSupplierCodeGeneratorTests {
assertThat(compiled.getSourceFile()).contains(
"getBeanFactory().getBean(InnerComponentConfiguration.class).new EnvironmentAwareComponent(");
});
assertThat(getReflectionHints().getTypeHint(EnvironmentAwareComponent.class))
.satisfies(hasConstructorWithMode(ExecutableMode.INTROSPECT));
assertThat(getReflectionHints().getTypeHint(EnvironmentAwareComponent.class)).isNotNull();
}
@Test
@ -184,8 +180,7 @@ class InstanceSupplierCodeGeneratorTests {
assertThat(bean).extracting("number").isNull(); // No property actually set
assertThat(compiled.getSourceFile()).contains("NumberHolderFactoryBean::new");
});
assertThat(getReflectionHints().getTypeHint(NumberHolderFactoryBean.class))
.satisfies(hasConstructorWithMode(ExecutableMode.INTROSPECT));
assertThat(getReflectionHints().getTypeHint(NumberHolderFactoryBean.class)).isNotNull();
}
@Test
@ -215,8 +210,7 @@ class InstanceSupplierCodeGeneratorTests {
assertThat(compiled.getSourceFile()).contains(
"getBeanFactory().getBean(\"config\", SimpleConfiguration.class).stringBean()");
});
assertThat(getReflectionHints().getTypeHint(SimpleConfiguration.class))
.satisfies(hasMethodWithMode(ExecutableMode.INTROSPECT));
assertThat(getReflectionHints().getTypeHint(SimpleConfiguration.class)).isNotNull();
}
@Test
@ -232,8 +226,7 @@ class InstanceSupplierCodeGeneratorTests {
assertThat(compiled.getSourceFile()).contains(
"getBeanFactory().getBean(\"config\", DefaultSimpleBeanContract.class).simpleBean()");
});
assertThat(getReflectionHints().getTypeHint(SimpleBeanContract.class))
.satisfies(hasMethodWithMode(ExecutableMode.INTROSPECT));
assertThat(getReflectionHints().getTypeHint(SimpleBeanContract.class)).isNotNull();
}
@Test
@ -268,8 +261,7 @@ class InstanceSupplierCodeGeneratorTests {
assertThat(compiled.getSourceFile())
.contains("(registeredBean) -> SimpleConfiguration.integerBean()");
});
assertThat(getReflectionHints().getTypeHint(SimpleConfiguration.class))
.satisfies(hasMethodWithMode(ExecutableMode.INTROSPECT));
assertThat(getReflectionHints().getTypeHint(SimpleConfiguration.class)).isNotNull();
}
@Test
@ -287,8 +279,7 @@ class InstanceSupplierCodeGeneratorTests {
assertThat(bean).isEqualTo("42test");
assertThat(compiled.getSourceFile()).contains("SampleFactory.create(");
});
assertThat(getReflectionHints().getTypeHint(SampleFactory.class))
.satisfies(hasMethodWithMode(ExecutableMode.INTROSPECT));
assertThat(getReflectionHints().getTypeHint(SampleFactory.class)).isNotNull();
}
@Test
@ -305,8 +296,7 @@ class InstanceSupplierCodeGeneratorTests {
assertThat(bean).isEqualTo(42);
assertThat(compiled.getSourceFile()).doesNotContain(") throws Exception {");
});
assertThat(getReflectionHints().getTypeHint(SimpleConfiguration.class))
.satisfies(hasMethodWithMode(ExecutableMode.INTROSPECT));
assertThat(getReflectionHints().getTypeHint(SimpleConfiguration.class)).isNotNull();
}

View File

@ -56,8 +56,7 @@ class InstanceSupplierCodeGeneratorKotlinTests {
Assertions.assertThat(bean).isInstanceOf(KotlinTestBean::class.java)
Assertions.assertThat(compiled.sourceFile).contains("InstanceSupplier.using(KotlinTestBean::new)")
}
Assertions.assertThat(getReflectionHints().getTypeHint(KotlinTestBean::class.java))
.satisfies(hasConstructorWithMode(ExecutableMode.INTROSPECT))
Assertions.assertThat(getReflectionHints().getTypeHint(KotlinTestBean::class.java)).isNotNull
}
@Test
@ -90,8 +89,7 @@ class InstanceSupplierCodeGeneratorKotlinTests {
"getBeanFactory().getBean(\"config\", KotlinConfiguration.class).stringBean()"
)
}
Assertions.assertThat<TypeHint?>(getReflectionHints().getTypeHint(KotlinConfiguration::class.java))
.satisfies(hasMethodWithMode(ExecutableMode.INTROSPECT))
Assertions.assertThat<TypeHint?>(getReflectionHints().getTypeHint(KotlinConfiguration::class.java)).isNotNull
}
@Test

View File

@ -960,7 +960,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
return CodeBlock.of("$L.resolveAndSet($L, $L)", resolver,
REGISTERED_BEAN_PARAMETER, INSTANCE_PARAMETER);
}
hints.reflection().registerMethod(method, ExecutableMode.INTROSPECT);
hints.reflection().registerType(method.getDeclaringClass());
return CodeBlock.of("$L.$L($L.resolve($L))", INSTANCE_PARAMETER,
method.getName(), resolver, REGISTERED_BEAN_PARAMETER);

View File

@ -40,7 +40,6 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.autoproxy.AutoProxyUtils;
import org.springframework.aot.generate.GeneratedMethod;
import org.springframework.aot.generate.GenerationContext;
import org.springframework.aot.hint.ExecutableMode;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.ResourceHints;
import org.springframework.aot.hint.RuntimeHints;
@ -812,7 +811,7 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
Executable userExecutable = instantiationDescriptor.executable();
if (userExecutable instanceof Constructor<?> userConstructor) {
try {
runtimeHints.reflection().registerConstructor(userConstructor, ExecutableMode.INTROSPECT);
runtimeHints.reflection().registerType(userConstructor.getDeclaringClass());
Constructor<?> constructor = this.proxyClass.getConstructor(userExecutable.getParameterTypes());
return new InstantiationDescriptor(constructor);
}

View File

@ -17,7 +17,6 @@
package org.springframework.context.aot;
import org.springframework.aot.generate.GenerationContext;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.beans.factory.aot.BeanRegistrationAotContribution;
import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor;
@ -61,7 +60,7 @@ class KotlinReflectionBeanRegistrationAotProcessor implements BeanRegistrationAo
private void registerHints(Class<?> type, RuntimeHints runtimeHints) {
if (KotlinDetector.isKotlinType(type)) {
runtimeHints.reflection().registerType(type, MemberCategory.INTROSPECT_DECLARED_METHODS);
runtimeHints.reflection().registerType(type);
}
Class<?> superClass = type.getSuperclass();
if (superClass != null) {

View File

@ -237,7 +237,7 @@ class BeanValidationBeanRegistrationAotProcessor implements BeanRegistrationAotP
public void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) {
ReflectionHints hints = generationContext.getRuntimeHints().reflection();
for (Class<?> validatedClass : this.validatedClasses) {
hints.registerType(validatedClass, MemberCategory.DECLARED_FIELDS);
hints.registerType(validatedClass, MemberCategory.INVOKE_DECLARED_FIELDS);
}
for (Class<? extends ConstraintValidator<?, ?>> constraintValidatorClass : this.constraintValidatorClasses) {
hints.registerType(constraintValidatorClass, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);

View File

@ -534,7 +534,7 @@ class AnnotationConfigApplicationContextTests {
TypeReference cglibType = TypeReference.of(CglibConfiguration.class.getName() + "$$SpringCGLIB$$0");
assertThat(RuntimeHintsPredicates.reflection().onType(cglibType)
.withMemberCategories(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.DECLARED_FIELDS))
MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INVOKE_DECLARED_FIELDS))
.accepts(runtimeHints);
assertThat(RuntimeHintsPredicates.reflection().onType(CglibConfiguration.class)
.withMemberCategories(MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_DECLARED_METHODS))

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2024 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.
@ -102,7 +102,7 @@ class ContextAotProcessorTests {
assertThat(directory.resolve(
"source/org/springframework/context/aot/ContextAotProcessorTests_SampleApplication__BeanFactoryRegistrations.java"))
.exists().isRegularFile();
assertThat(directory.resolve("resource/META-INF/native-image/com.example/example/reflect-config.json"))
assertThat(directory.resolve("resource/META-INF/native-image/com.example/example/reachability-metadata.json"))
.exists().isRegularFile();
Path nativeImagePropertiesFile = directory
.resolve("resource/META-INF/native-image/com.example/example/native-image.properties");

View File

@ -24,7 +24,6 @@ import org.junit.jupiter.api.Test;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.test.agent.EnabledIfRuntimeHintsAgent;
import org.springframework.aot.test.agent.RuntimeHintsInvocations;
import org.springframework.aot.test.agent.RuntimeHintsRecorder;
import org.springframework.aot.test.generate.TestGenerationContext;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.RootBeanDefinition;
@ -46,6 +45,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Stephane Nicoll
*/
@EnabledIfRuntimeHintsAgent
@SuppressWarnings("removal")
class ApplicationContextAotGeneratorRuntimeHintsTests {
@Test
@ -100,7 +100,7 @@ class ApplicationContextAotGeneratorRuntimeHintsTests {
TestCompiler.forSystem().with(generationContext).compile(compiled -> {
ApplicationContextInitializer instance = compiled.getInstance(ApplicationContextInitializer.class);
GenericApplicationContext freshContext = new GenericApplicationContext();
RuntimeHintsInvocations recordedInvocations = RuntimeHintsRecorder.record(() -> {
RuntimeHintsInvocations recordedInvocations = org.springframework.aot.test.agent.RuntimeHintsRecorder.record(() -> {
instance.initialize(freshContext);
freshContext.refresh();
freshContext.close();

View File

@ -79,7 +79,7 @@ class BeanValidationBeanRegistrationAotProcessorTests {
process(MethodParameterLevelConstraint.class);
assertThat(this.generationContext.getRuntimeHints().reflection().typeHints()).hasSize(2);
assertThat(RuntimeHintsPredicates.reflection().onType(MethodParameterLevelConstraint.class)
.withMemberCategory(MemberCategory.DECLARED_FIELDS)).accepts(this.generationContext.getRuntimeHints());
.withMemberCategory(MemberCategory.INVOKE_DECLARED_FIELDS)).accepts(this.generationContext.getRuntimeHints());
assertThat(RuntimeHintsPredicates.reflection().onType(ExistsValidator.class)
.withMemberCategory(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)).accepts(this.generationContext.getRuntimeHints());
}
@ -89,7 +89,7 @@ class BeanValidationBeanRegistrationAotProcessorTests {
process(ConstructorParameterLevelConstraint.class);
assertThat(this.generationContext.getRuntimeHints().reflection().typeHints()).hasSize(2);
assertThat(RuntimeHintsPredicates.reflection().onType(ConstructorParameterLevelConstraint.class)
.withMemberCategory(MemberCategory.DECLARED_FIELDS)).accepts(this.generationContext.getRuntimeHints());
.withMemberCategory(MemberCategory.INVOKE_DECLARED_FIELDS)).accepts(this.generationContext.getRuntimeHints());
assertThat(RuntimeHintsPredicates.reflection().onType(ExistsValidator.class)
.withMemberCategory(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)).accepts(this.generationContext.getRuntimeHints());
}
@ -99,7 +99,7 @@ class BeanValidationBeanRegistrationAotProcessorTests {
process(PropertyLevelConstraint.class);
assertThat(this.generationContext.getRuntimeHints().reflection().typeHints()).hasSize(2);
assertThat(RuntimeHintsPredicates.reflection().onType(PropertyLevelConstraint.class)
.withMemberCategory(MemberCategory.DECLARED_FIELDS)).accepts(this.generationContext.getRuntimeHints());
.withMemberCategory(MemberCategory.INVOKE_DECLARED_FIELDS)).accepts(this.generationContext.getRuntimeHints());
assertThat(RuntimeHintsPredicates.reflection().onType(ExistsValidator.class)
.withMemberCategory(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)).accepts(this.generationContext.getRuntimeHints());
}
@ -109,7 +109,7 @@ class BeanValidationBeanRegistrationAotProcessorTests {
process(GenericTypeLevelConstraint.class);
assertThat(this.generationContext.getRuntimeHints().reflection().typeHints()).hasSize(2);
assertThat(RuntimeHintsPredicates.reflection().onType(GenericTypeLevelConstraint.class)
.withMemberCategory(MemberCategory.DECLARED_FIELDS)).accepts(this.generationContext.getRuntimeHints());
.withMemberCategory(MemberCategory.INVOKE_DECLARED_FIELDS)).accepts(this.generationContext.getRuntimeHints());
assertThat(RuntimeHintsPredicates.reflection().onType(PatternValidator.class)
.withMemberCategory(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)).accepts(this.generationContext.getRuntimeHints());
}
@ -119,9 +119,9 @@ class BeanValidationBeanRegistrationAotProcessorTests {
process(TransitiveGenericTypeLevelConstraint.class);
assertThat(this.generationContext.getRuntimeHints().reflection().typeHints()).hasSize(3);
assertThat(RuntimeHintsPredicates.reflection().onType(TransitiveGenericTypeLevelConstraint.class)
.withMemberCategory(MemberCategory.DECLARED_FIELDS)).accepts(this.generationContext.getRuntimeHints());
.withMemberCategory(MemberCategory.INVOKE_DECLARED_FIELDS)).accepts(this.generationContext.getRuntimeHints());
assertThat(RuntimeHintsPredicates.reflection().onType(Exclude.class)
.withMemberCategory(MemberCategory.DECLARED_FIELDS)).accepts(this.generationContext.getRuntimeHints());
.withMemberCategory(MemberCategory.INVOKE_DECLARED_FIELDS)).accepts(this.generationContext.getRuntimeHints());
assertThat(RuntimeHintsPredicates.reflection().onType(PatternValidator.class)
.withMemberCategory(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)).accepts(this.generationContext.getRuntimeHints());
}
@ -132,7 +132,7 @@ class BeanValidationBeanRegistrationAotProcessorTests {
process(beanClass);
assertThat(this.generationContext.getRuntimeHints().reflection().typeHints()).hasSize(1);
assertThat(RuntimeHintsPredicates.reflection().onType(beanClass)
.withMemberCategory(MemberCategory.DECLARED_FIELDS)).accepts(this.generationContext.getRuntimeHints());
.withMemberCategory(MemberCategory.INVOKE_DECLARED_FIELDS)).accepts(this.generationContext.getRuntimeHints());
}
@Test // gh-33940

View File

@ -48,16 +48,11 @@ class KotlinReflectionBeanRegistrationAotProcessorTests {
@Test
fun shouldProcessKotlinBean() {
process(SampleKotlinBean::class.java)
assertThat(RuntimeHintsPredicates.reflection().onType(SampleKotlinBean::class.java))
.accepts(generationContext.runtimeHints)
assertThat(
RuntimeHintsPredicates.reflection()
.onType(SampleKotlinBean::class.java)
.withMemberCategory(MemberCategory.INTROSPECT_DECLARED_METHODS)
).accepts(generationContext.runtimeHints)
assertThat(
RuntimeHintsPredicates.reflection()
.onType(BaseKotlinBean::class.java)
.withMemberCategory(MemberCategory.INTROSPECT_DECLARED_METHODS)
).accepts(generationContext.runtimeHints)
RuntimeHintsPredicates.reflection().onType(BaseKotlinBean::class.java))
.accepts(generationContext.runtimeHints)
}
@Test
@ -72,7 +67,6 @@ class KotlinReflectionBeanRegistrationAotProcessorTests {
assertThat(
RuntimeHintsPredicates.reflection()
.onType(OuterBean.NestedBean::class.java)
.withMemberCategory(MemberCategory.INTROSPECT_DECLARED_METHODS)
.and(RuntimeHintsPredicates.reflection().onType(OuterBean::class.java))
).accepts(generationContext.runtimeHints)
}

View File

@ -100,7 +100,7 @@ public class BindingReflectionHintsRegistrar {
typeHint.withMembers(MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS,
MemberCategory.INVOKE_PUBLIC_METHODS);
}
typeHint.withMembers(MemberCategory.DECLARED_FIELDS,
typeHint.withMembers(MemberCategory.INVOKE_DECLARED_FIELDS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
for (Method method : clazz.getMethods()) {
String methodName = method.getName();
@ -120,8 +120,6 @@ public class BindingReflectionHintsRegistrar {
if (KotlinDetector.isKotlinType(clazz)) {
KotlinDelegate.registerComponentHints(hints, clazz);
registerKotlinSerializationHints(hints, clazz);
// For Kotlin reflection
typeHint.withMembers(MemberCategory.INTROSPECT_DECLARED_METHODS);
}
});
}

View File

@ -44,7 +44,7 @@ public abstract class ClassHintUtils {
private static final Consumer<TypeHint.Builder> asClassBasedProxy = hint ->
hint.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.INVOKE_DECLARED_METHODS,
MemberCategory.DECLARED_FIELDS);
MemberCategory.INVOKE_DECLARED_FIELDS);
private static final Consumer<TypeHint.Builder> asProxiedUserClass = hint ->
hint.withMembers(MemberCategory.INVOKE_PUBLIC_METHODS,

View File

@ -54,7 +54,7 @@ class BindingReflectionHintsRegistrarTests {
.satisfies(typeHint -> {
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(SampleEmptyClass.class));
assertThat(typeHint.getMemberCategories()).containsExactlyInAnyOrder(
MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
MemberCategory.INVOKE_DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
assertThat(typeHint.constructors()).isEmpty();
assertThat(typeHint.fields()).isEmpty();
assertThat(typeHint.methods()).isEmpty();
@ -68,7 +68,7 @@ class BindingReflectionHintsRegistrarTests {
typeHint -> {
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(SampleEmptyClass.class));
assertThat(typeHint.getMemberCategories()).containsExactlyInAnyOrder(
MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
MemberCategory.INVOKE_DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
assertThat(typeHint.constructors()).isEmpty();
assertThat(typeHint.fields()).isEmpty();
assertThat(typeHint.methods()).isEmpty();
@ -76,7 +76,7 @@ class BindingReflectionHintsRegistrarTests {
typeHint -> {
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(SampleExtendingClass.class));
assertThat(typeHint.getMemberCategories()).containsExactlyInAnyOrder(
MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
MemberCategory.INVOKE_DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
assertThat(typeHint.constructors()).isEmpty();
assertThat(typeHint.fields()).isEmpty();
assertThat(typeHint.methods()).isEmpty();
@ -198,7 +198,7 @@ class BindingReflectionHintsRegistrarTests {
typeHint -> {
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(ResolvableType.class));
assertThat(typeHint.getMemberCategories()).containsExactlyInAnyOrder(
MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
MemberCategory.INVOKE_DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
assertThat(typeHint.constructors()).isEmpty();
assertThat(typeHint.fields()).isEmpty();
assertThat(typeHint.methods()).hasSizeGreaterThan(1);

View File

@ -78,8 +78,7 @@ class BindingReflectionHintsRegistrarKotlinTests {
@Test
fun `Register reflection hints on declared methods for Kotlin class`() {
bindingRegistrar.registerReflectionHints(hints.reflection(), SampleClass::class.java)
assertThat(RuntimeHintsPredicates.reflection().onType(SampleClass::class.java)
.withMemberCategory(MemberCategory.INTROSPECT_DECLARED_METHODS)).accepts(hints)
assertThat(RuntimeHintsPredicates.reflection().onType(SampleClass::class.java)).accepts(hints)
}
}

View File

@ -54,7 +54,7 @@ class MessageMappingReflectiveProcessorTests {
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(OutgoingMessage.class));
assertThat(typeHint.getMemberCategories()).containsExactlyInAnyOrder(
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.DECLARED_FIELDS);
MemberCategory.INVOKE_DECLARED_FIELDS);
assertThat(typeHint.methods()).satisfiesExactlyInAnyOrder(
hint -> assertThat(hint.getName()).isEqualTo("getMessage"),
hint -> assertThat(hint.getName()).isEqualTo("setMessage"));
@ -72,7 +72,7 @@ class MessageMappingReflectiveProcessorTests {
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(IncomingMessage.class));
assertThat(typeHint.getMemberCategories()).containsExactlyInAnyOrder(
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.DECLARED_FIELDS);
MemberCategory.INVOKE_DECLARED_FIELDS);
assertThat(typeHint.methods()).satisfiesExactlyInAnyOrder(
hint -> assertThat(hint.getName()).isEqualTo("getMessage"),
hint -> assertThat(hint.getName()).isEqualTo("setMessage"));

View File

@ -85,18 +85,18 @@ class PersistenceManagedTypesBeanRegistrationAotProcessorTests {
context.registerBean(JpaDomainConfiguration.class);
contributeHints(context, hints -> {
assertThat(RuntimeHintsPredicates.reflection().onType(DriversLicense.class)
.withMemberCategories(MemberCategory.DECLARED_FIELDS)).accepts(hints);
.withMemberCategories(MemberCategory.INVOKE_DECLARED_FIELDS)).accepts(hints);
assertThat(RuntimeHintsPredicates.reflection().onType(Person.class)
.withMemberCategories(MemberCategory.DECLARED_FIELDS)).accepts(hints);
.withMemberCategories(MemberCategory.INVOKE_DECLARED_FIELDS)).accepts(hints);
assertThat(RuntimeHintsPredicates.reflection().onType(PersonListener.class)
.withMemberCategories(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS))
.accepts(hints);
assertThat(RuntimeHintsPredicates.reflection().onType(Employee.class)
.withMemberCategories(MemberCategory.DECLARED_FIELDS)).accepts(hints);
.withMemberCategories(MemberCategory.INVOKE_DECLARED_FIELDS)).accepts(hints);
assertThat(RuntimeHintsPredicates.reflection().onMethod(Employee.class, "preRemove"))
.accepts(hints);
assertThat(RuntimeHintsPredicates.reflection().onType(EmployeeId.class)
.withMemberCategories(MemberCategory.DECLARED_FIELDS)).accepts(hints);
.withMemberCategories(MemberCategory.INVOKE_DECLARED_FIELDS)).accepts(hints);
assertThat(RuntimeHintsPredicates.reflection().onType(EmployeeLocationConverter.class)
.withMemberCategories(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)).accepts(hints);
assertThat(RuntimeHintsPredicates.reflection().onType(EmployeeCategoryConverter.class)
@ -104,7 +104,7 @@ class PersistenceManagedTypesBeanRegistrationAotProcessorTests {
assertThat(RuntimeHintsPredicates.reflection().onType(EmployeeKindConverter.class)
.withMemberCategories(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)).accepts(hints);
assertThat(RuntimeHintsPredicates.reflection().onType(EmployeeLocation.class)
.withMemberCategories(MemberCategory.DECLARED_FIELDS)).accepts(hints);
.withMemberCategories(MemberCategory.INVOKE_DECLARED_FIELDS)).accepts(hints);
});
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 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.
@ -144,7 +144,7 @@ class MergedContextConfigurationRuntimeHints {
if (!pattern.endsWith(SLASH)) {
pattern += SLASH;
}
pattern += "*";
pattern += "**";
runtimeHints.resources().registerPattern(pattern);
}
}

View File

@ -79,8 +79,7 @@ class TestAotProcessorTests extends AbstractAotTests {
assertThat(findFiles(sourceOutput)).containsExactlyInAnyOrderElementsOf(expectedSourceFiles());
assertThat(findFiles(resourceOutput.resolve("META-INF/native-image"))).contains(
Path.of(groupId, artifactId, "reflect-config.json"),
Path.of(groupId, artifactId, "resource-config.json"));
Path.of(groupId, artifactId, "reachability-metadata.json"));
}
private void copy(Class<?> testClass, Path destination) {

View File

@ -37,7 +37,7 @@ class TransactionRuntimeHints implements RuntimeHintsRegistrar {
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
hints.reflection().registerTypes(
TypeReference.listOf(Isolation.class, Propagation.class),
TypeHint.builtWith(MemberCategory.DECLARED_FIELDS));
TypeHint.builtWith(MemberCategory.INVOKE_DECLARED_FIELDS));
}
}

View File

@ -48,7 +48,7 @@ class ControllerMappingReflectiveProcessorTests {
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(Response.class));
assertThat(typeHint.getMemberCategories()).containsExactlyInAnyOrder(
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.DECLARED_FIELDS);
MemberCategory.INVOKE_DECLARED_FIELDS);
assertThat(typeHint.methods()).satisfiesExactlyInAnyOrder(
hint -> assertThat(hint.getName()).isEqualTo("getMessage"),
hint -> assertThat(hint.getName()).isEqualTo("setMessage"));
@ -66,7 +66,7 @@ class ControllerMappingReflectiveProcessorTests {
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(Request.class));
assertThat(typeHint.getMemberCategories()).containsExactlyInAnyOrder(
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.DECLARED_FIELDS);
MemberCategory.INVOKE_DECLARED_FIELDS);
assertThat(typeHint.methods()).satisfiesExactlyInAnyOrder(
hint -> assertThat(hint.getName()).isEqualTo("getMessage"),
hint -> assertThat(hint.getName()).isEqualTo("setMessage"));
@ -84,7 +84,7 @@ class ControllerMappingReflectiveProcessorTests {
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(Request.class));
assertThat(typeHint.getMemberCategories()).containsExactlyInAnyOrder(
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.DECLARED_FIELDS);
MemberCategory.INVOKE_DECLARED_FIELDS);
assertThat(typeHint.methods()).satisfiesExactlyInAnyOrder(
hint -> assertThat(hint.getName()).isEqualTo("getMessage"),
hint -> assertThat(hint.getName()).isEqualTo("setMessage"));
@ -102,7 +102,7 @@ class ControllerMappingReflectiveProcessorTests {
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(Response.class));
assertThat(typeHint.getMemberCategories()).containsExactlyInAnyOrder(
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.DECLARED_FIELDS);
MemberCategory.INVOKE_DECLARED_FIELDS);
assertThat(typeHint.methods()).satisfiesExactlyInAnyOrder(
hint -> assertThat(hint.getName()).isEqualTo("getMessage"),
hint -> assertThat(hint.getName()).isEqualTo("setMessage"));
@ -141,7 +141,7 @@ class ControllerMappingReflectiveProcessorTests {
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(Response.class));
assertThat(typeHint.getMemberCategories()).containsExactlyInAnyOrder(
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.DECLARED_FIELDS);
MemberCategory.INVOKE_DECLARED_FIELDS);
assertThat(typeHint.methods()).satisfiesExactlyInAnyOrder(
hint -> assertThat(hint.getName()).isEqualTo("getMessage"),
hint -> assertThat(hint.getName()).isEqualTo("setMessage"));
@ -167,7 +167,7 @@ class ControllerMappingReflectiveProcessorTests {
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(Request.class));
assertThat(typeHint.getMemberCategories()).containsExactlyInAnyOrder(
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.DECLARED_FIELDS);
MemberCategory.INVOKE_DECLARED_FIELDS);
assertThat(typeHint.methods()).satisfiesExactlyInAnyOrder(
hint -> assertThat(hint.getName()).isEqualTo("getMessage"),
hint -> assertThat(hint.getName()).isEqualTo("setMessage"));
@ -193,7 +193,7 @@ class ControllerMappingReflectiveProcessorTests {
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(Request.class));
assertThat(typeHint.getMemberCategories()).containsExactlyInAnyOrder(
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.DECLARED_FIELDS);
MemberCategory.INVOKE_DECLARED_FIELDS);
assertThat(typeHint.methods()).satisfiesExactlyInAnyOrder(
hint -> assertThat(hint.getName()).isEqualTo("getMessage"),
hint -> assertThat(hint.getName()).isEqualTo("setMessage"));