What are @ConditionalOnClass and @ConditionalOnMissingClass, and why does Spring Boot auto-configuration rely on them?
answer
- classpath presence, not bean presence
- ASM metadata read -> no NoClassDefFoundError
- backbone of Boot auto-config (Jackson/Web/DataSource)
- value = Class vs name = String
- multiple classes = AND
basics
~10 s@ConditionalOnClass makes a bean/config load only if a named class is on the classpath; @ConditionalOnMissingClass only if it's absent. Boot uses them so auto-config activates just when the relevant library is present.
solid answer
~40 s@ConditionalOnClass registers a bean or configuration only when the referenced class(es) exist on the classpath; @ConditionalOnMissingClass is the inverse. They are the backbone of Spring Boot auto-configuration: DataSourceAutoConfiguration only kicks in if a JDBC driver/HikariCP is present, WebMvcAutoConfiguration only if DispatcherServlet is present. Because the annotation is evaluated by reading class metadata (ASM), you can reference a type that may be absent without a NoClassDefFoundError — you pass the class via the value attribute or its name as a String. This 'react to what's on the classpath' model is why adding a starter dependency is often enough to get working defaults with zero configuration.
code
java · 16 lines// Only configure a Jackson ObjectMapper bean when Jackson is on the classpath
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(ObjectMapper.class)
public class MyJacksonConfig {
@Bean
@ConditionalOnMissingBean
ObjectMapper objectMapper() {
return new ObjectMapper();
}
}
// String form when the referenced type may be absent from this loader
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(name = "io.micrometer.core.instrument.MeterRegistry")
class OptionalMetricsConfig { /* ... */ }go deeper
Know it gates config on classpath presence and is why adding a starter 'just works'.
Explain the ASM-metadata trick and value-vs-name attribute forms.
Contrast with @ConditionalOnBean and describe short-circuiting whole auto-config classes.
Discuss evaluation timing and how OnClassCondition avoids classloading during auto-config ordering.
## What they are `@ConditionalOnClass` and `@ConditionalOnMissingClass` are part of Spring Boot's `@Conditional` family (package `org.springframework.boot.autoconfigure.condition`). A `@Conditional` annotation attaches a `Condition` to a bean method or `@Configuration` class; Spring only registers that bean/config if the condition returns `true`. - **`@ConditionalOnClass`** — matches when the named class(es) are **present** on the classpath. - **`@ConditionalOnMissingClass`** — matches when the named class(es) are **absent**. ## Why auto-configuration needs them Spring Boot ships dozens of auto-configuration classes (listed in `META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports`). They are all on the classpath, but most must stay **inert** unless the relevant library is actually present. Example: `JacksonAutoConfiguration` is guarded by `@ConditionalOnClass(ObjectMapper.class)` — no Jackson jar, no Jackson beans. This is the essence of 'convention over configuration': you add `spring-boot-starter-web`, the servlet/web classes appear, and the web auto-configs light up. ## The key trick: metadata, not class loading A naive check like `Class.forName(...)` would throw `NoClassDefFoundError` when the class is missing — defeating the purpose. Boot avoids this by evaluating conditions from **bytecode metadata via ASM** (`OnClassCondition` reads the annotation attributes without loading the referenced type). That is why you can safely write `@ConditionalOnClass(ObjectMapper.class)` on a config class even in an app where Jackson is absent. ### Two ways to name the class ```java @ConditionalOnClass(ObjectMapper.class) // typed – fine when THIS class can load it @ConditionalOnClass(name = "com.foo.Optional") // string – use when the type may be absent here ``` When the guarding class itself would fail to load the referenced type, use the `name`/`value` String form. In practice, on the **class/method being annotated**, the referenced type is read from the annotation metadata so the typed form is safe; you reach for the `name` attribute mostly for readability or truly optional deps. ## Placement and semantics - Can annotate a `@Configuration` class (gates everything inside) or a single `@Bean` method. - Multiple classes = **AND**: all must be present (`OnClass`) / all absent (`OnMissingClass`). - Evaluated at **context-refresh / bean-definition** time, before beans are instantiated. ## Edge cases & gotchas - **Classpath, not runtime state.** It answers 'is this type available?', not 'is a bean of it defined?' — that's `@ConditionalOnBean`. - **Order in auto-config.** `@ConditionalOnClass` at the top of an `@AutoConfiguration` class short-circuits the whole class cheaply, which is why Boot puts it there. - **User code.** You can use these in your own `@Configuration` to provide optional integrations (e.g., a bean only when a monitoring library is on the classpath). ## When to use Use `@ConditionalOnClass` when a feature only makes sense if a library is present; `@ConditionalOnMissingClass` to provide a fallback when a library is deliberately absent.
- Why doesn't @ConditionalOnClass(SomeMissingType.class) throw NoClassDefFoundError when the type is absent?Boot's OnClassCondition reads the annotation attributes from the class file's metadata using ASM instead of loading the referenced type, so the missing class is never actually resolved by the classloader during evaluation.
- What's the difference between @ConditionalOnClass and @ConditionalOnBean?@ConditionalOnClass checks whether a TYPE exists on the classpath; @ConditionalOnBean checks whether a bean DEFINITION of a type already exists in the context. Classpath availability vs. runtime bean presence are different questions.
saying these in an interview costs you the question
- Claiming it checks whether a bean exists (that's @ConditionalOnBean)
- Saying it uses Class.forName and can throw NoClassDefFoundError
- Thinking multiple classes mean OR instead of AND