diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/BeanRegistry.java b/spring-beans/src/main/java/org/springframework/beans/factory/BeanRegistry.java index 2b10257bf99..896d03debe9 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/BeanRegistry.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/BeanRegistry.java @@ -79,6 +79,13 @@ public interface BeanRegistry { */ void registerBean(String name, Class beanClass, Consumer> customizer); + /** + * Register beans using given {@link BeanRegistrar}. + * @param registrar the bean registrar that will be called to register + * additional beans + */ + void register(BeanRegistrar registrar); + /** * Specification for customizing a bean. * @param the bean type diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanRegistryAdapter.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanRegistryAdapter.java index fd100df49d8..da1073f3884 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanRegistryAdapter.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanRegistryAdapter.java @@ -32,6 +32,8 @@ import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionCustomizer; import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.ResolvableType; +import org.springframework.core.env.Environment; +import org.springframework.util.Assert; import org.springframework.util.MultiValueMap; /** @@ -47,21 +49,26 @@ public class BeanRegistryAdapter implements BeanRegistry { private final ListableBeanFactory beanFactory; + private final Environment environment; + private final Class beanRegistrarClass; private final @Nullable MultiValueMap customizers; public BeanRegistryAdapter(BeanDefinitionRegistry beanRegistry, ListableBeanFactory beanFactory, - Class beanRegistrarClass) { - this(beanRegistry, beanFactory, beanRegistrarClass, null); + Environment environment, Class beanRegistrarClass) { + + this(beanRegistry, beanFactory, environment, beanRegistrarClass, null); } public BeanRegistryAdapter(BeanDefinitionRegistry beanRegistry, ListableBeanFactory beanFactory, - Class beanRegistrarClass, @Nullable MultiValueMap customizers) { + Environment environment, Class beanRegistrarClass, + @Nullable MultiValueMap customizers) { this.beanRegistry = beanRegistry; this.beanFactory = beanFactory; + this.environment = environment; this.beanRegistrarClass = beanRegistrarClass; this.customizers = customizers; } @@ -103,6 +110,12 @@ public class BeanRegistryAdapter implements BeanRegistry { this.beanRegistry.registerBeanDefinition(name, beanDefinition); } + @Override + public void register(BeanRegistrar registrar) { + Assert.notNull(registrar, "'registrar' must not be null"); + registrar.register(this, this.environment); + } + /** * {@link RootBeanDefinition} subclass for {@code #registerBean} based diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/support/BeanRegistryAdapterTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/support/BeanRegistryAdapterTests.java index 5b3f632a4ee..08c69f812f9 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/support/BeanRegistryAdapterTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/support/BeanRegistryAdapterTests.java @@ -43,7 +43,7 @@ public class BeanRegistryAdapterTests { @Test void defaultBackgroundInit() { - BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, DefaultBeanRegistrar.class); + BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class); new DefaultBeanRegistrar().register(adapter, env); AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) this.beanFactory.getBeanDefinition("foo"); assertThat(beanDefinition.isBackgroundInit()).isFalse(); @@ -51,7 +51,7 @@ public class BeanRegistryAdapterTests { @Test void enableBackgroundInit() { - BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, BackgroundInitBeanRegistrar.class); + BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, BackgroundInitBeanRegistrar.class); new BackgroundInitBeanRegistrar().register(adapter, env); AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) this.beanFactory.getBeanDefinition("foo"); assertThat(beanDefinition.isBackgroundInit()).isTrue(); @@ -59,7 +59,7 @@ public class BeanRegistryAdapterTests { @Test void defaultDescription() { - BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, DefaultBeanRegistrar.class); + BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class); new DefaultBeanRegistrar().register(adapter, env); BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("foo"); assertThat(beanDefinition.getDescription()).isNull(); @@ -67,7 +67,7 @@ public class BeanRegistryAdapterTests { @Test void customDescription() { - BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, CustomDescriptionBeanRegistrar.class); + BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, CustomDescriptionBeanRegistrar.class); new CustomDescriptionBeanRegistrar().register(adapter, env); BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("foo"); assertThat(beanDefinition.getDescription()).isEqualTo("custom"); @@ -75,7 +75,7 @@ public class BeanRegistryAdapterTests { @Test void defaultFallback() { - BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, DefaultBeanRegistrar.class); + BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class); new DefaultBeanRegistrar().register(adapter, env); BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("foo"); assertThat(beanDefinition.isFallback()).isFalse(); @@ -83,7 +83,7 @@ public class BeanRegistryAdapterTests { @Test void enableFallback() { - BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, FallbackBeanRegistrar.class); + BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, FallbackBeanRegistrar.class); new FallbackBeanRegistrar().register(adapter, env); BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("foo"); assertThat(beanDefinition.isFallback()).isTrue(); @@ -91,7 +91,7 @@ public class BeanRegistryAdapterTests { @Test void defaultRole() { - BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, DefaultBeanRegistrar.class); + BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class); new DefaultBeanRegistrar().register(adapter, env); BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("foo"); assertThat(beanDefinition.getRole()).isEqualTo(AbstractBeanDefinition.ROLE_APPLICATION); @@ -99,7 +99,7 @@ public class BeanRegistryAdapterTests { @Test void infrastructureRole() { - BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, InfrastructureBeanRegistrar.class); + BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, InfrastructureBeanRegistrar.class); new InfrastructureBeanRegistrar().register(adapter, env); BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("foo"); assertThat(beanDefinition.getRole()).isEqualTo(AbstractBeanDefinition.ROLE_INFRASTRUCTURE); @@ -107,7 +107,7 @@ public class BeanRegistryAdapterTests { @Test void defaultLazyInit() { - BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, DefaultBeanRegistrar.class); + BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class); new DefaultBeanRegistrar().register(adapter, env); AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) this.beanFactory.getBeanDefinition("foo"); assertThat(beanDefinition.isLazyInit()).isFalse(); @@ -115,7 +115,7 @@ public class BeanRegistryAdapterTests { @Test void enableLazyInit() { - BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, LazyInitBeanRegistrar.class); + BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, LazyInitBeanRegistrar.class); new LazyInitBeanRegistrar().register(adapter, env); AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) this.beanFactory.getBeanDefinition("foo"); assertThat(beanDefinition.isLazyInit()).isTrue(); @@ -123,7 +123,7 @@ public class BeanRegistryAdapterTests { @Test void defaultAutowirable() { - BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, DefaultBeanRegistrar.class); + BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class); new DefaultBeanRegistrar().register(adapter, env); AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) this.beanFactory.getBeanDefinition("foo"); assertThat(beanDefinition.isAutowireCandidate()).isTrue(); @@ -131,7 +131,7 @@ public class BeanRegistryAdapterTests { @Test void notAutowirable() { - BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, NotAutowirableBeanRegistrar.class); + BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, NotAutowirableBeanRegistrar.class); new NotAutowirableBeanRegistrar().register(adapter, env); AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) this.beanFactory.getBeanDefinition("foo"); assertThat(beanDefinition.isAutowireCandidate()).isFalse(); @@ -139,7 +139,7 @@ public class BeanRegistryAdapterTests { @Test void defaultOrder() { - BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, DefaultBeanRegistrar.class); + BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class); new DefaultBeanRegistrar().register(adapter, env); AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) this.beanFactory.getBeanDefinition("foo"); Integer order = (Integer)beanDefinition.getAttribute(AbstractBeanDefinition.ORDER_ATTRIBUTE); @@ -148,7 +148,7 @@ public class BeanRegistryAdapterTests { @Test void customOrder() { - BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, CustomOrderBeanRegistrar.class); + BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, CustomOrderBeanRegistrar.class); new CustomOrderBeanRegistrar().register(adapter, env); AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) this.beanFactory.getBeanDefinition("foo"); Integer order = (Integer)beanDefinition.getAttribute(AbstractBeanDefinition.ORDER_ATTRIBUTE); @@ -157,7 +157,7 @@ public class BeanRegistryAdapterTests { @Test void defaultPrimary() { - BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, DefaultBeanRegistrar.class); + BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class); new DefaultBeanRegistrar().register(adapter, env); BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("foo"); assertThat(beanDefinition.isPrimary()).isFalse(); @@ -165,7 +165,7 @@ public class BeanRegistryAdapterTests { @Test void enablePrimary() { - BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, PrimaryBeanRegistrar.class); + BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, PrimaryBeanRegistrar.class); new PrimaryBeanRegistrar().register(adapter, env); BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("foo"); assertThat(beanDefinition.isPrimary()).isTrue(); @@ -173,7 +173,7 @@ public class BeanRegistryAdapterTests { @Test void defaultScope() { - BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, DefaultBeanRegistrar.class); + BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class); new DefaultBeanRegistrar().register(adapter, env); BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("foo"); assertThat(beanDefinition.getScope()).isEqualTo(AbstractBeanDefinition.SCOPE_DEFAULT); @@ -181,7 +181,7 @@ public class BeanRegistryAdapterTests { @Test void prototypeScope() { - BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, PrototypeBeanRegistrar.class); + BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, PrototypeBeanRegistrar.class); new PrototypeBeanRegistrar().register(adapter, env); BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("foo"); assertThat(beanDefinition.getScope()).isEqualTo(AbstractBeanDefinition.SCOPE_PROTOTYPE); @@ -189,7 +189,7 @@ public class BeanRegistryAdapterTests { @Test void defaultSupplier() { - BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, DefaultBeanRegistrar.class); + BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class); new DefaultBeanRegistrar().register(adapter, env); AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition)this.beanFactory.getBeanDefinition("foo"); assertThat(beanDefinition.getInstanceSupplier()).isNull(); @@ -197,7 +197,7 @@ public class BeanRegistryAdapterTests { @Test void customSupplier() { - BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, SupplierBeanRegistrar.class); + BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, SupplierBeanRegistrar.class); new SupplierBeanRegistrar().register(adapter, env); AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition)this.beanFactory.getBeanDefinition("foo"); Supplier supplier = beanDefinition.getInstanceSupplier(); @@ -221,6 +221,14 @@ public class BeanRegistryAdapterTests { assertThat(beanDefinition.getResolvableType().resolveGeneric(0)).isEqualTo(Foo.class); } + @Test + void registerViaAnotherRegistrar() { + BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class); + BeanRegistrar registrar = (registry, env) -> registry.register(new DefaultBeanRegistrar()); + registrar.register(adapter, env); + assertThat(this.beanFactory.getBeanDefinition("foo")).isNotNull(); + } + private static class DefaultBeanRegistrar implements BeanRegistrar { 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 1688542e13f..de14187568c 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 @@ -409,7 +409,7 @@ class ConfigurationClassBeanDefinitionReader { "Cannot support bean registrars since " + this.registry.getClass().getName() + " does not implement BeanDefinitionRegistry"); registrars.forEach(registrar -> registrar.register(new BeanRegistryAdapter(this.registry, - (ListableBeanFactory) this.registry, registrar.getClass()), this.environment)); + (ListableBeanFactory) this.registry, this.environment, registrar.getClass()), this.environment)); } 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 57f6ee7d6ae..5596c1d166d 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 @@ -936,10 +936,10 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo private CodeBlock generateRegisterCode() { Builder code = CodeBlock.builder(); for (BeanRegistrar beanRegistrar : this.beanRegistrars) { - code.addStatement("new $T().register(new $T(($T)$L, $L, $T.class, $L), $L)", beanRegistrar.getClass(), + code.addStatement("new $T().register(new $T(($T)$L, $L, $L, $T.class, $L), $L)", beanRegistrar.getClass(), BeanRegistryAdapter.class, BeanDefinitionRegistry.class, BeanFactoryInitializationCode.BEAN_FACTORY_VARIABLE, - BeanFactoryInitializationCode.BEAN_FACTORY_VARIABLE, beanRegistrar.getClass(), CUSTOMIZER_MAP_VARIABLE, - ENVIRONMENT_VARIABLE); + BeanFactoryInitializationCode.BEAN_FACTORY_VARIABLE, ENVIRONMENT_VARIABLE, beanRegistrar.getClass(), + CUSTOMIZER_MAP_VARIABLE, ENVIRONMENT_VARIABLE); } return code.build(); }