diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java index 3974df96813..65305db42c1 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java @@ -27,6 +27,7 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.function.Predicate; import java.util.function.Supplier; @@ -40,6 +41,7 @@ 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; import org.springframework.aot.hint.TypeReference; @@ -650,6 +652,7 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo @Override public void applyTo(GenerationContext generationContext, BeanFactoryInitializationCode beanFactoryInitializationCode) { + registerRuntimeHints(generationContext.getRuntimeHints()); GeneratedMethod generatedMethod = beanFactoryInitializationCode .getMethods() .add("processPropertySources", this::generateAddPropertySourceProcessorMethod); @@ -657,6 +660,13 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo .addInitializer(generatedMethod.toMethodReference()); } + private void registerRuntimeHints(RuntimeHints hints) { + this.descriptors.stream().map(PropertySourceDescriptor::propertySourceFactory) + .filter(Objects::nonNull).distinct() + .forEach(factory -> hints.reflection() + .registerType(factory, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)); + } + private void generateAddPropertySourceProcessorMethod(MethodSpec.Builder method) { method.addJavadoc("Apply known @PropertySources to the environment."); method.addModifiers(Modifier.PRIVATE); diff --git a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorAotContributionTests.java b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorAotContributionTests.java index 80a784c1b00..efd9a97cb47 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorAotContributionTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorAotContributionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 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. @@ -29,7 +29,9 @@ import org.junit.jupiter.api.Test; import org.springframework.aot.generate.MethodReference; import org.springframework.aot.generate.MethodReference.ArgumentCodeGenerator; +import org.springframework.aot.hint.MemberCategory; import org.springframework.aot.hint.ResourcePatternHint; +import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; import org.springframework.aot.test.generate.TestGenerationContext; import org.springframework.beans.BeansException; import org.springframework.beans.factory.InitializingBean; @@ -50,6 +52,7 @@ import org.springframework.context.testfixture.context.generator.SimpleComponent import org.springframework.core.Ordered; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.io.ResourceLoader; +import org.springframework.core.io.support.DefaultPropertySourceFactory; import org.springframework.core.test.tools.Compiled; import org.springframework.core.test.tools.TestCompiler; import org.springframework.core.type.AnnotationMetadata; @@ -291,6 +294,16 @@ class ConfigurationClassPostProcessorAotContributionTests { }); } + @Test + void applyToWhenHasCustomFactoryRegistersHints() { + BeanFactoryInitializationAotContribution contribution = getContribution( + PropertySourceWithCustomFactoryConfiguration.class); + contribution.applyTo(generationContext, beanFactoryInitializationCode); + assertThat(RuntimeHintsPredicates.reflection().onType(CustomPropertySourcesFactory.class) + .withMemberCategories(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)) + .accepts(generationContext.getRuntimeHints()); + } + @SuppressWarnings("unchecked") private void compile(BiConsumer, Compiled> result) { MethodReference methodReference = beanFactoryInitializationCode.getInitializers().get(0); @@ -332,6 +345,13 @@ class ConfigurationClassPostProcessorAotContributionTests { } + @Configuration(proxyBeanMethods = false) + @PropertySource(value = "classpath:org/springframework/context/annotation/p1.properties", + factory = CustomPropertySourcesFactory.class) + static class PropertySourceWithCustomFactoryConfiguration { + + } + } @Nested @@ -379,4 +399,8 @@ class ConfigurationClassPostProcessorAotContributionTests { .containsExactly(entry(key.getName(), value.getName())); } + static class CustomPropertySourcesFactory extends DefaultPropertySourceFactory { + + } + }