Under The Hood
backend springboot Spring Boot 3.x

Auto-Configuration: @ConditionalOnClass, @ConditionalOnMissingBean

Last updated
Prerequisites:
Spring configuration and beans basics
Understanding of @Configuration and @Bean
  • spring
  • spring-boot
  • auto-configuration
  • conditional
  • ConditionalOnClass
  • ConditionalOnMissingBean

Read at your depth

The practical view

Spring Boot auto-configuration creates beans automatically based on what's on the classpath and your properties. It's driven by @Conditional annotations: @ConditionalOnClass(name = "org.h2.Driver") creates the bean only if that class is present; @ConditionalOnMissingBean(DataSource.class) only if you haven't defined your own; @ConditionalOnProperty, @ConditionalOnExpression, @ConditionalOnWebApplication. Your own @Configuration classes are processed AFTER auto-configuration, so a bean you define with the same type overrides the auto-configured one (via @ConditionalOnMissingBean).

The same idea in other frameworks

react equivalent
N/A — server-side Spring Boot concern.

Legacy vs modern

Hand-wiring beans vs auto-configuration with conditionals

Manually configuring beans for every dependency is boilerplate; Boot's conditional auto-configuration creates sensible defaults that back off when you override.

before → after
Manual bean wiring (pre-Boot)
@Bean
DataSource dataSource() {
  return new DriverManagerDataSource("jdbc:h2:mem:test", "sa", ""); // ❌ OLD: hand-wired
}
Conditional auto-configuration
// spring-boot-starter-jdbc on the classpath + application.properties
// spring.datasource.url=...  →  ✅ NEW: DataSource auto-configured

Interview gotchas

Context

This tests the bean-definition timing model — interviewers want to know that the missing-bean check happens during registration, so ordering (user config vs auto-config) determines the outcome.

The mechanical answer

@ConditionalOnMissingBean is evaluated when the auto-configuration class's bean definitions are being registered. It checks whether a bean definition of the specified type already exists at that moment. Because user-defined @Configuration classes are processed BEFORE auto-configuration classes (by design), a user bean is typically visible and the auto-configured bean backs off. However, if a bean is defined in a way that registers later (e.g. another auto-configuration ordered after, a @Bean defined in an @Import processed later, or a bean created from a factory that hasn't registered yet), the condition may not see it, and BOTH beans get created — leading to ambiguity. The fix is to understand the ordering (use @AutoConfigureBefore/After or define the override early) and that the check is registration-time, not injection-time.

Trap

The naive answer is 'if I define a bean, auto-configuration always skips'. The check is timing-sensitive and registration-based; late-registered beans can coexist with the auto-configured one, causing a NoUniqueBeanDefinitionException. Another trap: thinking @ConditionalOnMissingBean checks at runtime — it's evaluated at bean-definition registration during context refresh. Candidates who describe the registration-order model show real understanding.

Under The Hood — a multi-depth technical interview hub.

Third-party licenses Press ⌘ K to search.