Skip to content

Commit 181b352

Browse files
committed
Properly honor conditions on overriding bean methods
Issue: SPR-12694 (cherry picked from commit 981aefc)
1 parent 6c47b5f commit 181b352

File tree

3 files changed

+73
-19
lines changed

3 files changed

+73
-19
lines changed

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.context.annotation;
1818

19+
import java.util.HashSet;
1920
import java.util.LinkedHashMap;
2021
import java.util.LinkedHashSet;
2122
import java.util.Map;
@@ -63,6 +64,8 @@ final class ConfigurationClass {
6364
private final Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars =
6465
new LinkedHashMap<ImportBeanDefinitionRegistrar, AnnotationMetadata>();
6566

67+
final Set<String> skippedBeans = new HashSet<String>();
68+
6669

6770
/**
6871
* Create a new {@link ConfigurationClass} with the given name.

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

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -182,16 +182,37 @@ private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationCl
182182
* with the BeanDefinitionRegistry based on its contents.
183183
*/
184184
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
185-
if (this.conditionEvaluator.shouldSkip(beanMethod.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
185+
ConfigurationClass configClass = beanMethod.getConfigurationClass();
186+
MethodMetadata metadata = beanMethod.getMetadata();
187+
188+
// Consider name and any aliases
189+
AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
190+
List<String> names = new ArrayList<String>(Arrays.asList(bean.getStringArray("name")));
191+
String beanName = (names.size() > 0 ? names.remove(0) : beanMethod.getMetadata().getMethodName());
192+
193+
// Do we need to mark the bean as skipped by its condition?
194+
if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
195+
configClass.skippedBeans.add(beanName);
196+
return;
197+
}
198+
if (configClass.skippedBeans.contains(beanName)) {
186199
return;
187200
}
188201

189-
ConfigurationClass configClass = beanMethod.getConfigurationClass();
190-
MethodMetadata metadata = beanMethod.getMetadata();
202+
// Register aliases even when overridden
203+
for (String alias : names) {
204+
this.registry.registerAlias(beanName, alias);
205+
}
206+
207+
// Has this effectively been overridden before (e.g. via XML)?
208+
if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
209+
return;
210+
}
191211

192212
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
193213
beanDef.setResource(configClass.getResource());
194214
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
215+
195216
if (metadata.isStatic()) {
196217
// static @Bean method
197218
beanDef.setBeanClassName(configClass.getMetadata().getClassName());
@@ -205,19 +226,6 @@ private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
205226
beanDef.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
206227
beanDef.setAttribute(RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
207228

208-
// Consider name and any aliases
209-
AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
210-
List<String> names = new ArrayList<String>(Arrays.asList(bean.getStringArray("name")));
211-
String beanName = (names.size() > 0 ? names.remove(0) : beanMethod.getMetadata().getMethodName());
212-
for (String alias : names) {
213-
this.registry.registerAlias(beanName, alias);
214-
}
215-
216-
// Has this effectively been overridden before (e.g. via XML)?
217-
if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
218-
return;
219-
}
220-
221229
AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
222230

223231
Autowire autowire = bean.getEnum("autowire");

spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassWithConditionTests.java

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -39,6 +39,7 @@
3939
* Test for {@link Conditional} beans.
4040
*
4141
* @author Phillip Webb
42+
* @author Juergen Hoeller
4243
*/
4344
@SuppressWarnings("resource")
4445
public class ConfigurationClassWithConditionTests {
@@ -117,6 +118,19 @@ public void importsNotCreated() throws Exception {
117118
ctx.refresh();
118119
}
119120

121+
@Test
122+
public void conditionOnOverriddenMethodHonored() {
123+
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigWithBeanSkipped.class);
124+
assertEquals(0, context.getBeansOfType(ExampleBean.class).size());
125+
}
126+
127+
@Test
128+
public void noConditionOnOverriddenMethodHonored() {
129+
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigWithBeanReactivated.class);
130+
assertEquals(1, context.getBeansOfType(ExampleBean.class).size());
131+
}
132+
133+
120134
@Configuration
121135
static class BeanOneConfiguration {
122136
@Bean
@@ -197,6 +211,7 @@ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata)
197211
}
198212

199213
static class NeverCondition implements Condition {
214+
200215
@Override
201216
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
202217
return false;
@@ -261,4 +276,32 @@ public String[] selectImports(AnnotationMetadata importingClassMetadata) {
261276
static class ExampleBean {
262277
}
263278

279+
@Configuration
280+
private static class ConfigWithBeanActive {
281+
282+
@Bean
283+
public ExampleBean baz() {
284+
return new ExampleBean();
285+
}
286+
}
287+
288+
private static class ConfigWithBeanSkipped extends ConfigWithBeanActive {
289+
290+
@Override
291+
@Bean
292+
@Conditional(NeverCondition.class)
293+
public ExampleBean baz() {
294+
return new ExampleBean();
295+
}
296+
}
297+
298+
private static class ConfigWithBeanReactivated extends ConfigWithBeanSkipped {
299+
300+
@Override
301+
@Bean
302+
public ExampleBean baz() {
303+
return new ExampleBean();
304+
}
305+
}
306+
264307
}

0 commit comments

Comments
 (0)