Understanding Spring @Enable Annotation Logic and the Role of ConfigurationClassPostProcessor
This article explains how Spring's @Enable annotations are driven by @Import, walks through the entry points in spring.handlers, details the processing flow of ConfigurationClassPostProcessor, distinguishes full and lightweight configuration modes, and describes the CGLIB enhancement that ensures proper @Bean method semantics.
The article examines the internal mechanism of Spring's @Enable annotations (e.g., @EnableEurekaClient , @EnableFeignClients , @EnableCircuitBreaker , @EnableHystrix ) and explains that they are powered by @Import , which loads specific configuration parsers.
To locate the entry point, the author points out that the @Enable modules rely on the AnnotationConfigBeanDefinitionParser registered in /META-INF/spring.handlers . The relevant source snippet is shown below:
public class ContextNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
// ... other code omitted
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
}
}The core processor, ConfigurationClassPostProcessor , scans for @Component , @Configuration , and @Bean definitions, delegating the heavy lifting to ConfigurationClassParser , which parses candidate classes into ConfigurationClass objects and then hands them to ConfigurationClassBeanDefinitionReader to create bean definitions.
The processing sequence performed by ConfigurationClassPostProcessor is:
Sort candidates by @Order value.
Parse @Configuration classes.
Read configuration class information and generate BeanDefinition s.
Register ImportRegistry as a bean to support @Import aware classes.
Spring distinguishes between "full" and "lightweight" configuration modes: a class annotated with @Configuration is a full‑mode configuration, while @Component and plain @Bean methods are lightweight.
For full‑mode configurations, Spring applies a CGLIB enhancement via ConfigurationClassEnhancer . The enhancer creates a subclass that overrides each @Bean method. The first call to a @Bean method creates the bean; subsequent calls return the already‑created bean from the container, preserving singleton semantics.
Key code excerpt of the enhancer’s purpose (from the class comment) is reproduced below:
/**
* Enhances {@link Configuration} classes by generating a CGLIB subclass which
* interacts with the Spring container to respect bean scoping semantics for
* {@code @Bean} methods. Each such {@code @Bean} method will be overridden in
* the generated subclass, only delegating to the actual {@code @Bean} method
* implementation if the container actually requests the construction of a new
* instance. Otherwise, a call to such an {@code @Bean} method serves as a
* reference back to the container, obtaining the corresponding bean by name.
*/
class ConfigurationClassEnhancer { ... }In summary, the article clarifies that:
ConfigurationClassPostProcessor selects component, configuration, and bean definitions.
ConfigurationClassParser parses the selected candidates in the order: @PropertySource → @ComponentScan → @Import → @ImportResource → @Bean → default interface methods → superclass handling .
@Configuration classes are processed in full mode with CGLIB enhancement, while @Component and plain @Bean methods are lightweight.
The CGLIB subclass ensures that @Bean methods obey Spring's singleton lifecycle.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
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.