Why @Configuration Creates Proxies in Spring and Guarantees Singleton Beans
This article explains how Spring's @Configuration annotation triggers CGLIB proxy generation to manage @Bean methods, ensuring that internal calls return the same singleton instance, and contrasts this behavior with using @Component for configuration classes.
@Configuration is a class‑level annotation that marks a class as a source of bean definitions; methods annotated with @Bean declare beans, effectively replacing XML configuration and allowing flexible registration in the IoC container.
Simple Example
static class Person {}
@Configuration
static class AppConfig {
@Bean
public Person person() {
return new Person();
}
}Using @Component instead of @Configuration changes the behavior:
@Component
static class AppConfig {
@Bean
public Person person() {
return new Person();
}
}
try (GenericApplicationContext context = new GenericApplicationContext()) {
context.registerBean(AppConfig.class);
System.out.println(context.getBean(Person.class));
}When the class is annotated with @Configuration, multiple calls to person() return the same instance, while with @Component they return different instances, revealing the importance of the proxy mechanism.
How Spring Guarantees a Single Instance
Spring registers a ConfigurationClassPostProcessor, which is a BeanFactoryPostProcessor. It scans for @Configuration classes and marks them for proxy creation.
// proxyBeanMethods = true means a proxy will be generated
@Configuration(proxyBeanMethods = true)
static class AppConfig {}The marking is performed by ConfigurationClassUtils, which sets the attribute CONFIGURATION_CLASS_FULL (full) or CONFIGURATION_CLASS_LITE (lite) on the bean definition.
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
} else {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}During postProcessBeanFactory, Spring enhances the marked configuration classes by generating a CGLIB subclass:
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
// collect full‑configuration beans
// create proxy subclass via ConfigurationClassEnhancer
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
beanDef.setBeanClass(enhancedClass);
}
}The enhancer sets up callbacks, the most important being BeanMethodInterceptor:
private static class BeanMethodInterceptor implements MethodInterceptor {
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] args, MethodProxy proxy) throws Throwable {
ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
return resolveBeanReference(beanMethod, args, beanFactory, beanName);
}
}This interceptor looks up the bean by name in the container and returns the existing singleton, so internal method calls never create a new instance.
Consequently, using @Configuration ensures that all @Bean methods are proxied and that the container always provides the same bean instance, whereas @Component lacks this proxying, leading to multiple instances.
In summary, Spring’s proxy‑based mechanism, driven by ConfigurationClassPostProcessor, ConfigurationClassUtils, and ConfigurationClassEnhancer, guarantees the singleton semantics of beans defined in @Configuration classes.
Did you learn something?
Finished!!!
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
