Skip to content

Commit d689629

Browse files
committed
Support abstract @⁠Configuration classes without @⁠Bean methods again
Historically, @⁠Configuration classes that did not declare @⁠Bean methods were allowed to be abstract. However, the changes made in 76a6b9ea79 introduced a regression that prevents such classes from being abstract, resulting in a BeanInstantiationException. This change in behavior is caused by the fact that such a @⁠Configuration class is no longer replaced by a concrete subclass created dynamically by CGLIB. This commit restores support for abstract @⁠Configuration classes without @⁠Bean methods by modifying the "no enhancement required" check in ConfigurationClassParser. See gh-34486 Closes gh-34663 (cherry picked from commit 044258f)
1 parent 077721b commit d689629

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,9 @@ else if (bd instanceof AbstractBeanDefinition abstractBeanDef && abstractBeanDef
172172
}
173173

174174
// Downgrade to lite (no enhancement) in case of no instance-level @Bean methods.
175-
if (!configClass.hasNonStaticBeanMethods() && ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(
176-
bd.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE))) {
175+
if (!configClass.getMetadata().isAbstract() && !configClass.hasNonStaticBeanMethods() &&
176+
ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(
177+
bd.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE))) {
177178
bd.setAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE,
178179
ConfigurationClassUtils.CONFIGURATION_CLASS_LITE);
179180
}

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

+23-1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,22 @@ void enhancementIsPresentBecauseSingletonSemanticsAreRespectedUsingAsm() {
129129
assertThat(beanFactory.getDependentBeans("config")).contains("bar");
130130
}
131131

132+
@Test // gh-34663
133+
void enhancementIsPresentForAbstractConfigClassWithoutBeanMethods() {
134+
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(AbstractConfigWithoutBeanMethods.class));
135+
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
136+
pp.postProcessBeanFactory(beanFactory);
137+
RootBeanDefinition beanDefinition = (RootBeanDefinition) beanFactory.getBeanDefinition("config");
138+
assertThat(beanDefinition.hasBeanClass()).isTrue();
139+
assertThat(beanDefinition.getBeanClass().getName()).contains(ClassUtils.CGLIB_CLASS_SEPARATOR);
140+
Foo foo = beanFactory.getBean("foo", Foo.class);
141+
Bar bar = beanFactory.getBean("bar", Bar.class);
142+
assertThat(bar.foo).isSameAs(foo);
143+
assertThat(beanFactory.getDependentBeans("foo")).contains("bar");
144+
String[] dependentsOfSingletonBeanConfig = beanFactory.getDependentBeans(SingletonBeanConfig.class.getName());
145+
assertThat(dependentsOfSingletonBeanConfig).containsOnly("foo", "bar");
146+
}
147+
132148
@Test
133149
void enhancementIsNotPresentForProxyBeanMethodsFlagSetToFalse() {
134150
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(NonEnhancedSingletonBeanConfig.class));
@@ -181,7 +197,7 @@ void enhancementIsNotPresentForStaticMethodsUsingAsm() {
181197
assertThat(bar.foo).isNotSameAs(foo);
182198
}
183199

184-
@Test
200+
@Test // gh-34486
185201
void enhancementIsNotPresentWithEmptyConfig() {
186202
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(EmptyConfig.class));
187203
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
@@ -1187,6 +1203,12 @@ public static Bar bar() {
11871203
}
11881204
}
11891205

1206+
@Configuration
1207+
@Import(SingletonBeanConfig.class)
1208+
abstract static class AbstractConfigWithoutBeanMethods {
1209+
// This class intentionally does NOT declare @Bean methods.
1210+
}
1211+
11901212
@Configuration
11911213
static final class EmptyConfig {
11921214
}

0 commit comments

Comments
 (0)