Skip to content

Commit 789791e

Browse files
philwebbsdeleuze
authored andcommitted
Allow chained BeanRegistry registration
Add a `register(BeanRegistry registry)` method to `BeanRegistry` to allow registration chaining. See gh-34557
1 parent a0e2d3a commit 789791e

File tree

5 files changed

+55
-27
lines changed

5 files changed

+55
-27
lines changed

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ public interface BeanRegistry {
7979
*/
8080
<T> void registerBean(String name, Class<T> beanClass, Consumer<Spec<T>> customizer);
8181

82+
/**
83+
* Register beans using given {@link BeanRegistrar}.
84+
* @param registrar the bean registrar that will be called to register
85+
* additional beans
86+
*/
87+
void register(BeanRegistrar registrar);
88+
8289
/**
8390
* Specification for customizing a bean.
8491
* @param <T> the bean type

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

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
import org.springframework.beans.factory.config.BeanDefinitionCustomizer;
3333
import org.springframework.core.ParameterizedTypeReference;
3434
import org.springframework.core.ResolvableType;
35+
import org.springframework.core.env.Environment;
36+
import org.springframework.util.Assert;
3537
import org.springframework.util.MultiValueMap;
3638

3739
/**
@@ -47,21 +49,26 @@ public class BeanRegistryAdapter implements BeanRegistry {
4749

4850
private final ListableBeanFactory beanFactory;
4951

52+
private final Environment environment;
53+
5054
private final Class<? extends BeanRegistrar> beanRegistrarClass;
5155

5256
private final @Nullable MultiValueMap<String, BeanDefinitionCustomizer> customizers;
5357

5458

5559
public BeanRegistryAdapter(BeanDefinitionRegistry beanRegistry, ListableBeanFactory beanFactory,
56-
Class<? extends BeanRegistrar> beanRegistrarClass) {
57-
this(beanRegistry, beanFactory, beanRegistrarClass, null);
60+
Environment environment, Class<? extends BeanRegistrar> beanRegistrarClass) {
61+
62+
this(beanRegistry, beanFactory, environment, beanRegistrarClass, null);
5863
}
5964

6065
public BeanRegistryAdapter(BeanDefinitionRegistry beanRegistry, ListableBeanFactory beanFactory,
61-
Class<? extends BeanRegistrar> beanRegistrarClass, @Nullable MultiValueMap<String, BeanDefinitionCustomizer> customizers) {
66+
Environment environment, Class<? extends BeanRegistrar> beanRegistrarClass,
67+
@Nullable MultiValueMap<String, BeanDefinitionCustomizer> customizers) {
6268

6369
this.beanRegistry = beanRegistry;
6470
this.beanFactory = beanFactory;
71+
this.environment = environment;
6572
this.beanRegistrarClass = beanRegistrarClass;
6673
this.customizers = customizers;
6774
}
@@ -103,6 +110,12 @@ public <T> void registerBean(String name, Class<T> beanClass, Consumer<Spec<T>>
103110
this.beanRegistry.registerBeanDefinition(name, beanDefinition);
104111
}
105112

113+
@Override
114+
public void register(BeanRegistrar registrar) {
115+
Assert.notNull(registrar, "'registrar' must not be null");
116+
registrar.register(this, this.environment);
117+
}
118+
106119

107120
/**
108121
* {@link RootBeanDefinition} subclass for {@code #registerBean} based

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

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,103 +43,103 @@ public class BeanRegistryAdapterTests {
4343

4444
@Test
4545
void defaultBackgroundInit() {
46-
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, DefaultBeanRegistrar.class);
46+
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class);
4747
new DefaultBeanRegistrar().register(adapter, env);
4848
AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) this.beanFactory.getBeanDefinition("foo");
4949
assertThat(beanDefinition.isBackgroundInit()).isFalse();
5050
}
5151

5252
@Test
5353
void enableBackgroundInit() {
54-
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, BackgroundInitBeanRegistrar.class);
54+
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, BackgroundInitBeanRegistrar.class);
5555
new BackgroundInitBeanRegistrar().register(adapter, env);
5656
AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) this.beanFactory.getBeanDefinition("foo");
5757
assertThat(beanDefinition.isBackgroundInit()).isTrue();
5858
}
5959

6060
@Test
6161
void defaultDescription() {
62-
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, DefaultBeanRegistrar.class);
62+
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class);
6363
new DefaultBeanRegistrar().register(adapter, env);
6464
BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("foo");
6565
assertThat(beanDefinition.getDescription()).isNull();
6666
}
6767

6868
@Test
6969
void customDescription() {
70-
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, CustomDescriptionBeanRegistrar.class);
70+
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, CustomDescriptionBeanRegistrar.class);
7171
new CustomDescriptionBeanRegistrar().register(adapter, env);
7272
BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("foo");
7373
assertThat(beanDefinition.getDescription()).isEqualTo("custom");
7474
}
7575

7676
@Test
7777
void defaultFallback() {
78-
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, DefaultBeanRegistrar.class);
78+
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class);
7979
new DefaultBeanRegistrar().register(adapter, env);
8080
BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("foo");
8181
assertThat(beanDefinition.isFallback()).isFalse();
8282
}
8383

8484
@Test
8585
void enableFallback() {
86-
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, FallbackBeanRegistrar.class);
86+
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, FallbackBeanRegistrar.class);
8787
new FallbackBeanRegistrar().register(adapter, env);
8888
BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("foo");
8989
assertThat(beanDefinition.isFallback()).isTrue();
9090
}
9191

9292
@Test
9393
void defaultRole() {
94-
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, DefaultBeanRegistrar.class);
94+
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class);
9595
new DefaultBeanRegistrar().register(adapter, env);
9696
BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("foo");
9797
assertThat(beanDefinition.getRole()).isEqualTo(AbstractBeanDefinition.ROLE_APPLICATION);
9898
}
9999

100100
@Test
101101
void infrastructureRole() {
102-
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, InfrastructureBeanRegistrar.class);
102+
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, InfrastructureBeanRegistrar.class);
103103
new InfrastructureBeanRegistrar().register(adapter, env);
104104
BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("foo");
105105
assertThat(beanDefinition.getRole()).isEqualTo(AbstractBeanDefinition.ROLE_INFRASTRUCTURE);
106106
}
107107

108108
@Test
109109
void defaultLazyInit() {
110-
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, DefaultBeanRegistrar.class);
110+
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class);
111111
new DefaultBeanRegistrar().register(adapter, env);
112112
AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) this.beanFactory.getBeanDefinition("foo");
113113
assertThat(beanDefinition.isLazyInit()).isFalse();
114114
}
115115

116116
@Test
117117
void enableLazyInit() {
118-
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, LazyInitBeanRegistrar.class);
118+
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, LazyInitBeanRegistrar.class);
119119
new LazyInitBeanRegistrar().register(adapter, env);
120120
AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) this.beanFactory.getBeanDefinition("foo");
121121
assertThat(beanDefinition.isLazyInit()).isTrue();
122122
}
123123

124124
@Test
125125
void defaultAutowirable() {
126-
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, DefaultBeanRegistrar.class);
126+
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class);
127127
new DefaultBeanRegistrar().register(adapter, env);
128128
AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) this.beanFactory.getBeanDefinition("foo");
129129
assertThat(beanDefinition.isAutowireCandidate()).isTrue();
130130
}
131131

132132
@Test
133133
void notAutowirable() {
134-
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, NotAutowirableBeanRegistrar.class);
134+
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, NotAutowirableBeanRegistrar.class);
135135
new NotAutowirableBeanRegistrar().register(adapter, env);
136136
AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) this.beanFactory.getBeanDefinition("foo");
137137
assertThat(beanDefinition.isAutowireCandidate()).isFalse();
138138
}
139139

140140
@Test
141141
void defaultOrder() {
142-
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, DefaultBeanRegistrar.class);
142+
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class);
143143
new DefaultBeanRegistrar().register(adapter, env);
144144
AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) this.beanFactory.getBeanDefinition("foo");
145145
Integer order = (Integer)beanDefinition.getAttribute(AbstractBeanDefinition.ORDER_ATTRIBUTE);
@@ -148,7 +148,7 @@ void defaultOrder() {
148148

149149
@Test
150150
void customOrder() {
151-
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, CustomOrderBeanRegistrar.class);
151+
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, CustomOrderBeanRegistrar.class);
152152
new CustomOrderBeanRegistrar().register(adapter, env);
153153
AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) this.beanFactory.getBeanDefinition("foo");
154154
Integer order = (Integer)beanDefinition.getAttribute(AbstractBeanDefinition.ORDER_ATTRIBUTE);
@@ -157,47 +157,47 @@ void customOrder() {
157157

158158
@Test
159159
void defaultPrimary() {
160-
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, DefaultBeanRegistrar.class);
160+
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class);
161161
new DefaultBeanRegistrar().register(adapter, env);
162162
BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("foo");
163163
assertThat(beanDefinition.isPrimary()).isFalse();
164164
}
165165

166166
@Test
167167
void enablePrimary() {
168-
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, PrimaryBeanRegistrar.class);
168+
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, PrimaryBeanRegistrar.class);
169169
new PrimaryBeanRegistrar().register(adapter, env);
170170
BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("foo");
171171
assertThat(beanDefinition.isPrimary()).isTrue();
172172
}
173173

174174
@Test
175175
void defaultScope() {
176-
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, DefaultBeanRegistrar.class);
176+
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class);
177177
new DefaultBeanRegistrar().register(adapter, env);
178178
BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("foo");
179179
assertThat(beanDefinition.getScope()).isEqualTo(AbstractBeanDefinition.SCOPE_DEFAULT);
180180
}
181181

182182
@Test
183183
void prototypeScope() {
184-
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, PrototypeBeanRegistrar.class);
184+
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, PrototypeBeanRegistrar.class);
185185
new PrototypeBeanRegistrar().register(adapter, env);
186186
BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("foo");
187187
assertThat(beanDefinition.getScope()).isEqualTo(AbstractBeanDefinition.SCOPE_PROTOTYPE);
188188
}
189189

190190
@Test
191191
void defaultSupplier() {
192-
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, DefaultBeanRegistrar.class);
192+
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class);
193193
new DefaultBeanRegistrar().register(adapter, env);
194194
AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition)this.beanFactory.getBeanDefinition("foo");
195195
assertThat(beanDefinition.getInstanceSupplier()).isNull();
196196
}
197197

198198
@Test
199199
void customSupplier() {
200-
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, SupplierBeanRegistrar.class);
200+
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, SupplierBeanRegistrar.class);
201201
new SupplierBeanRegistrar().register(adapter, env);
202202
AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition)this.beanFactory.getBeanDefinition("foo");
203203
Supplier<?> supplier = beanDefinition.getInstanceSupplier();
@@ -221,6 +221,14 @@ void customTargetTypeFromTypeReference() {
221221
assertThat(beanDefinition.getResolvableType().resolveGeneric(0)).isEqualTo(Foo.class);
222222
}
223223

224+
@Test
225+
void registerViaAnotherRegistrar() {
226+
BeanRegistryAdapter adapter = new BeanRegistryAdapter(this.beanFactory, this.beanFactory, this.env, DefaultBeanRegistrar.class);
227+
BeanRegistrar registrar = (registry, env) -> registry.register(new DefaultBeanRegistrar());
228+
registrar.register(adapter, env);
229+
assertThat(this.beanFactory.getBeanDefinition("foo")).isNotNull();
230+
}
231+
224232

225233
private static class DefaultBeanRegistrar implements BeanRegistrar {
226234

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ private void loadBeanDefinitionsFromBeanRegistrars(Set<BeanRegistrar> registrars
409409
"Cannot support bean registrars since " + this.registry.getClass().getName() +
410410
" does not implement BeanDefinitionRegistry");
411411
registrars.forEach(registrar -> registrar.register(new BeanRegistryAdapter(this.registry,
412-
(ListableBeanFactory) this.registry, registrar.getClass()), this.environment));
412+
(ListableBeanFactory) this.registry, this.environment, registrar.getClass()), this.environment));
413413
}
414414

415415

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -936,10 +936,10 @@ private CodeBlock generateCustomizerMap() {
936936
private CodeBlock generateRegisterCode() {
937937
Builder code = CodeBlock.builder();
938938
for (BeanRegistrar beanRegistrar : this.beanRegistrars) {
939-
code.addStatement("new $T().register(new $T(($T)$L, $L, $T.class, $L), $L)", beanRegistrar.getClass(),
939+
code.addStatement("new $T().register(new $T(($T)$L, $L, $L, $T.class, $L), $L)", beanRegistrar.getClass(),
940940
BeanRegistryAdapter.class, BeanDefinitionRegistry.class, BeanFactoryInitializationCode.BEAN_FACTORY_VARIABLE,
941-
BeanFactoryInitializationCode.BEAN_FACTORY_VARIABLE, beanRegistrar.getClass(), CUSTOMIZER_MAP_VARIABLE,
942-
ENVIRONMENT_VARIABLE);
941+
BeanFactoryInitializationCode.BEAN_FACTORY_VARIABLE, ENVIRONMENT_VARIABLE, beanRegistrar.getClass(),
942+
CUSTOMIZER_MAP_VARIABLE, ENVIRONMENT_VARIABLE);
943943
}
944944
return code.build();
945945
}

0 commit comments

Comments
 (0)