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.