diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java index f0dab35258..5c02223ba6 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java @@ -16,6 +16,7 @@ package org.springframework.context.annotation; +import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; @@ -27,6 +28,7 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition; @@ -371,9 +373,11 @@ class ConfigurationClassBeanDefinitionReader { BeanDefinitionReader reader = readerInstanceCache.get(readerClass); if (reader == null) { try { + Constructor constructor = + readerClass.getDeclaredConstructor(BeanDefinitionRegistry.class); // Instantiate the specified BeanDefinitionReader - reader = readerClass.getConstructor(BeanDefinitionRegistry.class).newInstance(this.registry); - // Delegate the current ResourceLoader to it if possible + reader = BeanUtils.instantiateClass(constructor, this.registry); + // Delegate the current ResourceLoader and Environment to it if possible if (reader instanceof AbstractBeanDefinitionReader abdr) { abdr.setResourceLoader(this.resourceLoader); abdr.setEnvironment(this.environment); @@ -382,7 +386,7 @@ class ConfigurationClassBeanDefinitionReader { } catch (Throwable ex) { throw new IllegalStateException( - "Could not instantiate BeanDefinitionReader class [" + readerClass.getName() + "]"); + "Could not instantiate BeanDefinitionReader class [" + readerClass.getName() + "]", ex); } } reader.loadBeanDefinitions(resource); diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ImportResource.java b/spring-context/src/main/java/org/springframework/context/annotation/ImportResource.java index 3bdf24bac1..dbb1c6047d 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ImportResource.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ImportResource.java @@ -80,6 +80,10 @@ public @interface ImportResource { * {@link BeanDefinitionReader} implementation to use when processing * resources specified via the {@link #locations() locations} or * {@link #value() value} attribute. + *

The configured {@code BeanDefinitionReader} type must declare a + * constructor that accepts a single + * {@link org.springframework.beans.factory.support.BeanDefinitionRegistry + * BeanDefinitionRegistry} argument. *

By default, the reader will be adapted to the resource path specified: * {@code ".groovy"} files will be processed with a * {@link org.springframework.beans.factory.groovy.GroovyBeanDefinitionReader diff --git a/spring-context/src/test/java/org/springframework/context/annotation/configuration/ImportResourceTests.java b/spring-context/src/test/java/org/springframework/context/annotation/configuration/ImportResourceTests.java index b3811088ee..7b717f2c5a 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/configuration/ImportResourceTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/configuration/ImportResourceTests.java @@ -23,6 +23,7 @@ import org.junit.jupiter.api.Test; import org.springframework.aop.support.AopUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.testfixture.beans.TestBean; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; @@ -109,6 +110,13 @@ class ImportResourceTests { } } + @Test + void importResourceWithPrivateReader() { + try (AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ImportWithPrivateReaderConfig.class)) { + assertThat(ctx.containsBean("propertiesDeclaredBean")).isTrue(); + } + } + @Configuration @ImportResource("classpath:org/springframework/context/annotation/configuration/ImportXmlConfig-context.xml") @@ -173,4 +181,20 @@ class ImportResourceTests { static class ImportNonXmlResourceConfig { } + @SuppressWarnings("deprecation") + @Configuration + @ImportResource(locations = "org/springframework/context/annotation/configuration/ImportNonXmlResourceConfig.properties", + reader = PrivatePropertiesBeanDefinitionReader.class) + static class ImportWithPrivateReaderConfig { + } + + @SuppressWarnings("deprecation") + private static class PrivatePropertiesBeanDefinitionReader + extends org.springframework.beans.factory.support.PropertiesBeanDefinitionReader { + + PrivatePropertiesBeanDefinitionReader(BeanDefinitionRegistry registry) { + super(registry); + } + } + }