22
22
import java .util .Map ;
23
23
import java .util .Set ;
24
24
import java .util .concurrent .ConcurrentHashMap ;
25
- import java .util .function .Consumer ;
26
25
27
26
import org .springframework .aop .scope .ScopedProxyUtils ;
28
27
import org .springframework .beans .BeansException ;
28
+ import org .springframework .beans .factory .BeanFactory ;
29
29
import org .springframework .beans .factory .BeanFactoryUtils ;
30
30
import org .springframework .beans .factory .FactoryBean ;
31
31
import org .springframework .beans .factory .config .BeanDefinition ;
32
32
import org .springframework .beans .factory .config .BeanFactoryPostProcessor ;
33
33
import org .springframework .beans .factory .config .ConfigurableListableBeanFactory ;
34
- import org .springframework .beans .factory .config .ConstructorArgumentValues ;
35
- import org .springframework .beans .factory .config .RuntimeBeanReference ;
36
34
import org .springframework .beans .factory .config .SmartInstantiationAwareBeanPostProcessor ;
37
35
import org .springframework .beans .factory .support .BeanDefinitionRegistry ;
38
- import org .springframework .beans .factory .support .DefaultListableBeanFactory ;
39
36
import org .springframework .beans .factory .support .RootBeanDefinition ;
40
37
import org .springframework .core .Ordered ;
41
38
import org .springframework .core .PriorityOrdered ;
42
39
import org .springframework .core .ResolvableType ;
43
- import org .springframework .util .Assert ;
44
40
import org .springframework .util .StringUtils ;
45
41
46
42
/**
47
43
* A {@link BeanFactoryPostProcessor} implementation that processes test classes
48
- * and adapt the {@link BeanDefinitionRegistry} for any {@link BeanOverride} it
49
- * may define.
44
+ * and adapt the {@link BeanFactory} for any {@link BeanOverride} it may define.
50
45
*
51
46
* <p>A set of classes from which to parse {@link OverrideMetadata} must be
52
47
* provided to this processor. Each test class is expected to use any
66
61
*/
67
62
class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor , Ordered {
68
63
69
- private static final String INFRASTRUCTURE_BEAN_NAME = BeanOverrideBeanFactoryPostProcessor .class .getName ();
70
-
71
- private static final String EARLY_INFRASTRUCTURE_BEAN_NAME =
72
- BeanOverrideBeanFactoryPostProcessor .WrapEarlyBeanPostProcessor .class .getName ();
73
64
74
65
private final BeanOverrideRegistrar overrideRegistrar ;
75
66
@@ -94,14 +85,16 @@ public int getOrder() {
94
85
95
86
@ Override
96
87
public void postProcessBeanFactory (ConfigurableListableBeanFactory beanFactory ) throws BeansException {
97
- Assert .isInstanceOf (DefaultListableBeanFactory .class , beanFactory ,
98
- "Bean overriding annotations can only be used on a DefaultListableBeanFactory" );
99
- postProcessWithRegistry ((DefaultListableBeanFactory ) beanFactory );
88
+ if (!(beanFactory instanceof BeanDefinitionRegistry registry )) {
89
+ throw new IllegalStateException ("Cannot process bean override with a BeanFactory " +
90
+ "that doesn't implement BeanDefinitionRegistry: " + beanFactory .getClass ());
91
+ }
92
+ postProcessWithRegistry (beanFactory , registry );
100
93
}
101
94
102
- private void postProcessWithRegistry (DefaultListableBeanFactory registry ) {
95
+ private void postProcessWithRegistry (ConfigurableListableBeanFactory beanFactory , BeanDefinitionRegistry registry ) {
103
96
for (OverrideMetadata metadata : this .overrideRegistrar .getOverrideMetadata ()) {
104
- registerBeanOverride (registry , metadata );
97
+ registerBeanOverride (beanFactory , registry , metadata );
105
98
}
106
99
}
107
100
@@ -116,15 +109,20 @@ protected void copyBeanDefinitionDetails(BeanDefinition from, RootBeanDefinition
116
109
to .setScope (from .getScope ());
117
110
}
118
111
119
- private void registerBeanOverride (DefaultListableBeanFactory beanFactory , OverrideMetadata overrideMetadata ) {
112
+ private void registerBeanOverride (ConfigurableListableBeanFactory beanFactory , BeanDefinitionRegistry registry ,
113
+ OverrideMetadata overrideMetadata ) {
114
+
120
115
switch (overrideMetadata .getStrategy ()) {
121
- case REPLACE_DEFINITION -> registerReplaceDefinition (beanFactory , overrideMetadata , true );
122
- case REPLACE_OR_CREATE_DEFINITION -> registerReplaceDefinition (beanFactory , overrideMetadata , false );
116
+ case REPLACE_DEFINITION ->
117
+ registerReplaceDefinition (beanFactory , registry , overrideMetadata , true );
118
+ case REPLACE_OR_CREATE_DEFINITION ->
119
+ registerReplaceDefinition (beanFactory , registry , overrideMetadata , false );
123
120
case WRAP_BEAN -> registerWrapBean (beanFactory , overrideMetadata );
124
121
}
125
122
}
126
123
127
- private void registerReplaceDefinition (DefaultListableBeanFactory beanFactory , OverrideMetadata overrideMetadata , boolean enforceExistingDefinition ) {
124
+ private void registerReplaceDefinition (ConfigurableListableBeanFactory beanFactory , BeanDefinitionRegistry registry ,
125
+ OverrideMetadata overrideMetadata , boolean enforceExistingDefinition ) {
128
126
129
127
RootBeanDefinition beanDefinition = createBeanDefinition (overrideMetadata );
130
128
String beanName = overrideMetadata .getBeanName ();
@@ -133,13 +131,13 @@ private void registerReplaceDefinition(DefaultListableBeanFactory beanFactory, O
133
131
if (beanFactory .containsBeanDefinition (beanName )) {
134
132
existingBeanDefinition = beanFactory .getBeanDefinition (beanName );
135
133
copyBeanDefinitionDetails (existingBeanDefinition , beanDefinition );
136
- beanFactory .removeBeanDefinition (beanName );
134
+ registry .removeBeanDefinition (beanName );
137
135
}
138
136
else if (enforceExistingDefinition ) {
139
137
throw new IllegalStateException ("Unable to override bean '" + beanName + "'; there is no" +
140
138
" bean definition to replace with that name" );
141
139
}
142
- beanFactory .registerBeanDefinition (beanName , beanDefinition );
140
+ registry .registerBeanDefinition (beanName , beanDefinition );
143
141
144
142
Object override = overrideMetadata .createOverride (beanName , existingBeanDefinition , null );
145
143
if (beanFactory .isSingleton (beanName )) {
@@ -160,7 +158,7 @@ else if (enforceExistingDefinition) {
160
158
* upon creation, during the {@link WrapEarlyBeanPostProcessor#getEarlyBeanReference(Object, String)}
161
159
* phase.
162
160
*/
163
- private void registerWrapBean (DefaultListableBeanFactory beanFactory , OverrideMetadata metadata ) {
161
+ private void registerWrapBean (ConfigurableListableBeanFactory beanFactory , OverrideMetadata metadata ) {
164
162
Set <String > existingBeanNames = getExistingBeanNames (beanFactory , metadata .getBeanType ());
165
163
String beanName = metadata .getBeanName ();
166
164
if (!existingBeanNames .contains (beanName )) {
@@ -177,7 +175,7 @@ private RootBeanDefinition createBeanDefinition(OverrideMetadata metadata) {
177
175
return definition ;
178
176
}
179
177
180
- private Set <String > getExistingBeanNames (DefaultListableBeanFactory beanFactory , ResolvableType resolvableType ) {
178
+ private Set <String > getExistingBeanNames (ConfigurableListableBeanFactory beanFactory , ResolvableType resolvableType ) {
181
179
Set <String > beans = new LinkedHashSet <>(
182
180
Arrays .asList (beanFactory .getBeanNamesForType (resolvableType , true , false )));
183
181
Class <?> type = resolvableType .resolve (Object .class );
@@ -193,39 +191,6 @@ private Set<String> getExistingBeanNames(DefaultListableBeanFactory beanFactory,
193
191
return beans ;
194
192
}
195
193
196
- /**
197
- * Register a {@link BeanOverrideBeanFactoryPostProcessor} with a {@link BeanDefinitionRegistry}.
198
- * <p>Not required when using the Spring TestContext Framework, as registration
199
- * is automatic via the
200
- * {@link org.springframework.core.io.support.SpringFactoriesLoader SpringFactoriesLoader}
201
- * mechanism.
202
- * @param registry the bean definition registry
203
- */
204
- public static void register (BeanDefinitionRegistry registry ) {
205
- RuntimeBeanReference registrarReference = new RuntimeBeanReference (BeanOverrideRegistrar .INFRASTRUCTURE_BEAN_NAME );
206
- // Early processor
207
- addInfrastructureBeanDefinition (
208
- registry , WrapEarlyBeanPostProcessor .class , EARLY_INFRASTRUCTURE_BEAN_NAME , constructorArgs ->
209
- constructorArgs .addIndexedArgumentValue (0 , registrarReference ));
210
-
211
- // Main processor
212
- addInfrastructureBeanDefinition (
213
- registry , BeanOverrideBeanFactoryPostProcessor .class , INFRASTRUCTURE_BEAN_NAME , constructorArgs ->
214
- constructorArgs .addIndexedArgumentValue (0 , registrarReference ));
215
- }
216
-
217
- private static void addInfrastructureBeanDefinition (BeanDefinitionRegistry registry ,
218
- Class <?> clazz , String beanName , Consumer <ConstructorArgumentValues > constructorArgumentsConsumer ) {
219
-
220
- if (!registry .containsBeanDefinition (beanName )) {
221
- RootBeanDefinition definition = new RootBeanDefinition (clazz );
222
- definition .setRole (BeanDefinition .ROLE_INFRASTRUCTURE );
223
- ConstructorArgumentValues constructorArguments = definition .getConstructorArgumentValues ();
224
- constructorArgumentsConsumer .accept (constructorArguments );
225
- registry .registerBeanDefinition (beanName , definition );
226
- }
227
- }
228
-
229
194
230
195
static final class WrapEarlyBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor ,
231
196
PriorityOrdered {
0 commit comments