Browse Source

Allow chained BeanRegistry registration

Add a `register(BeanRegistry registry)` method to `BeanRegistry`
to allow registration chaining.

See gh-34557
pull/34571/head
Phillip Webb 9 months ago committed by Sébastien Deleuze
parent
commit
789791e186
  1. 7
      spring-beans/src/main/java/org/springframework/beans/factory/BeanRegistry.java
  2. 19
      spring-beans/src/main/java/org/springframework/beans/factory/support/BeanRegistryAdapter.java
  3. 48
      spring-beans/src/test/java/org/springframework/beans/factory/support/BeanRegistryAdapterTests.java
  4. 2
      spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java
  5. 6
      spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java

7
spring-beans/src/main/java/org/springframework/beans/factory/BeanRegistry.java

@ -79,6 +79,13 @@ public interface BeanRegistry { @@ -79,6 +79,13 @@ public interface BeanRegistry {
*/
<T> void registerBean(String name, Class<T> beanClass, Consumer<Spec<T>> 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 <T> the bean type

19
spring-beans/src/main/java/org/springframework/beans/factory/support/BeanRegistryAdapter.java

@ -32,6 +32,8 @@ import org.springframework.beans.factory.config.BeanDefinition; @@ -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 { @@ -47,21 +49,26 @@ public class BeanRegistryAdapter implements BeanRegistry {
private final ListableBeanFactory beanFactory;
private final Environment environment;
private final Class<? extends BeanRegistrar> beanRegistrarClass;
private final @Nullable MultiValueMap<String, BeanDefinitionCustomizer> customizers;
public BeanRegistryAdapter(BeanDefinitionRegistry beanRegistry, ListableBeanFactory beanFactory,
Class<? extends BeanRegistrar> beanRegistrarClass) {
this(beanRegistry, beanFactory, beanRegistrarClass, null);
Environment environment, Class<? extends BeanRegistrar> beanRegistrarClass) {
this(beanRegistry, beanFactory, environment, beanRegistrarClass, null);
}
public BeanRegistryAdapter(BeanDefinitionRegistry beanRegistry, ListableBeanFactory beanFactory,
Class<? extends BeanRegistrar> beanRegistrarClass, @Nullable MultiValueMap<String, BeanDefinitionCustomizer> customizers) {
Environment environment, Class<? extends BeanRegistrar> beanRegistrarClass,
@Nullable MultiValueMap<String, BeanDefinitionCustomizer> 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 { @@ -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

48
spring-beans/src/test/java/org/springframework/beans/factory/support/BeanRegistryAdapterTests.java

@ -43,7 +43,7 @@ public class BeanRegistryAdapterTests { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 {

2
spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java

@ -409,7 +409,7 @@ class ConfigurationClassBeanDefinitionReader { @@ -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));
}

6
spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java

@ -936,10 +936,10 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo @@ -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();
}

Loading…
Cancel
Save