Configuring Beans and Components
1. Creating Java Configuration Classes (@Configuration)
| Mode |
Behavior |
@Configuration |
Full mode — CGLIB-proxied; @Bean calls return same instance |
@Configuration(proxyBeanMethods=false) |
Lite mode — faster, no inter-bean call interception |
@Component with @Bean |
Lite mode by default |
2. Defining Beans with @Bean Methods
Example: @Bean with init and destroy lifecycle
@Configuration
public class AppConfig {
@Bean
RestClient httpClient(RestClient.Builder b) {
return b.baseUrl("https://api.example.com").build();
}
@Bean(initMethod="open", destroyMethod="close")
Connection conn() { return new Connection(); }
}
3. Setting Bean Names and Aliases
| Approach |
Result |
@Bean (default) |
Method name = bean id |
@Bean("primary") |
Custom name |
@Bean({"a","b"}) |
Name + aliases |
@Component("svcX") |
Custom name on stereotype |
4. Using @ComponentScan for Auto-Detection
Example: Selective component scan with exclusion
@SpringBootApplication
@ComponentScan(basePackages = {"com.example.api", "com.example.core"},
excludeFilters = @ComponentScan.Filter(Repository.class))
public class App {}
| Attribute |
Purpose |
basePackages |
Roots to scan |
basePackageClasses |
Type-safe alternative |
includeFilters / excludeFilters |
Annotation/AssignableType filters |
useDefaultFilters |
Disable automatic stereotype detection |
5. Importing Configurations (@Import, @ImportResource)
| Annotation |
Use |
@Import(OtherConfig.class) |
Pull in @Configuration class |
@Import(MyImportSelector.class) |
Dynamic class selection |
@Import(MyRegistrar.class) |
Programmatic bean registration |
@ImportResource("classpath:beans.xml") |
Legacy XML support |
6. Using Conditional Beans (@Conditional)
Example: OS-conditional bean
@Configuration
public class FeatureConfig {
@Bean
@Conditional(LinuxCondition.class)
EpollEventLoopGroup eventLoop() { return new EpollEventLoopGroup(); }
}
// Implementation
public class LinuxCondition implements Condition {
public boolean matches(ConditionContext ctx, AnnotatedTypeMetadata m) {
return System.getProperty("os.name").toLowerCase().contains("linux");
}
}
7. Using @ConditionalOnProperty Annotation
Example: Property-gated feature bean
@Bean
@ConditionalOnProperty(prefix="app.feature.x", name="enabled", havingValue="true", matchIfMissing=false)
FeatureXService featureX() { return new FeatureXService(); }
| Attribute |
Effect |
name |
Property key (relative to prefix) |
havingValue |
Required value (default any non-false) |
matchIfMissing |
Match when property absent |
8. Using @ConditionalOnClass and @ConditionalOnMissingClass
| Annotation |
Activates When |
@ConditionalOnClass(RedisOperations.class) |
Class on classpath |
@ConditionalOnMissingClass("javax.persistence.Entity") |
Class absent (string form to avoid load) |
@ConditionalOnWebApplication |
Servlet/reactive context |
@ConditionalOnNotWebApplication |
Non-web |
9. Using @ConditionalOnBean and @ConditionalOnMissingBean
Example: Default bean when none present
@Bean
@ConditionalOnMissingBean(MailSender.class)
MailSender defaultSender() { return new SmtpMailSender(); }
| Annotation |
Behavior |
@ConditionalOnBean(X.class) |
Activates if bean of type X already registered |
@ConditionalOnMissingBean |
User-defined override pattern |
| Order matters |
Use @AutoConfigureAfter in starters |
10. Ordering Beans with @Order and @Priority
| Mechanism |
Use Case |
@Order(int) |
Order in collections (lowest first) |
Ordered interface |
Programmatic ordering |
@Priority (jakarta) |
Used for autowiring tie-break |
Ordered.HIGHEST_PRECEDENCE |
Integer.MIN_VALUE |
Ordered.LOWEST_PRECEDENCE |
Integer.MAX_VALUE |
11. Customizing Bean Lifecycle (@PostConstruct, @PreDestroy)
Example: Lifecycle hooks: warm up and flush
@Component
public class CacheWarmer {
@PostConstruct void warm() { /* preload */ }
@PreDestroy void flush() { /* cleanup */ }
}
| Hook |
When Invoked |
@PostConstruct |
After deps injected |
@PreDestroy |
Before bean destroyed |
@Bean(initMethod, destroyMethod) |
For 3rd-party beans |
12. Using InitializingBean and DisposableBean Interfaces
| Interface |
Method |
Notes |
InitializingBean |
afterPropertiesSet() |
Called after deps injected |
DisposableBean |
destroy() |
Called on shutdown |
Note: Prefer JSR-250 annotations or @Bean(initMethod=…) to avoid
coupling to Spring interfaces.