Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow chained BeanRegistry registration #34557

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionCustomizer;
import org.springframework.core.ResolvableType;
import org.springframework.core.env.Environment;
import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;

/**
Expand All @@ -46,21 +48,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;
}
Expand Down Expand Up @@ -102,6 +109,12 @@ public <T> void registerBean(String name, Class<T> beanClass, Consumer<Spec<T>>
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,103 +41,103 @@ 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();
}

@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();
}

@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();
}

@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");
}

@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();
}

@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();
}

@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);
}

@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);
}

@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();
}

@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();
}

@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();
}

@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();
}

@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);
Expand All @@ -146,7 +146,7 @@ void defaultOrder() {

@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);
Expand All @@ -155,54 +155,62 @@ void customOrder() {

@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();
}

@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();
}

@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);
}

@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);
}

@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();
}

@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();
assertThat(supplier).isNotNull();
assertThat(supplier.get()).isNotNull().isInstanceOf(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 {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ private void loadBeanDefinitionsFromBeanRegistrars(Set<BeanRegistrar> registrars
"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));
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -936,10 +936,10 @@ private CodeBlock generateCustomizerMap() {
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();
}
Expand Down