Conditional annotations, how @EnableAutoConfiguration works internally, multiple beans of one type, how Boot chooses the web server and application type, listing beans, embedded containers, how Boot simplifies DI, the CLI today, excluding auto-configurations, non-web apps, @SpringBootApplication internals, back-off with @ConditionalOnMissingBean, replacing Tomcat and the core annotations.
Published September 25, 2026
Several of these questions also appear at the fresher level (see the fresher Spring Boot chapter). At 2–5 years, you're expected to explain the machinery: condition evaluation, bean-definition ordering, application-type detection, and how to debug all three.
Short answer: Conditional annotations register a bean or configuration class only if a condition holds when the context starts. They're how auto-configuration adapts to your classpath and properties without code changes:
| Annotation | Condition |
|---|---|
@ConditionalOnClass / @ConditionalOnMissingClass | A class is (or isn't) on the classpath |
@ConditionalOnBean / @ConditionalOnMissingBean | A bean of the given type exists (or doesn't) |
@ConditionalOnProperty | A property has a given value (feature toggles) |
@ConditionalOnWebApplication / @ConditionalOnNotWebApplication | The application type |
@ConditionalOnResource, @ConditionalOnExpression, @ConditionalOnJava, @ConditionalOnCloudPlatform | Other environment checks |
@Configuration
@ConditionalOnProperty(prefix = "features.fraud-check", name = "enabled", havingValue = "true")
class FraudCheckConfig {
@Bean FraudClient fraudClient(FraudProperties props) { return new FraudClient(props.url()); }
}
Key points to cover:
@Conditional + Condition interface. You can write custom conditions too.Learn it in depth → Auto-Configuration Mechanism
@EnableAutoConfiguration do, and how does auto-configuration work internally?Short answer: @EnableAutoConfiguration imports AutoConfigurationImportSelector. At startup, that selector:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports in every JAR. (Before Boot 2.7, the list was in spring.factories.)@ConditionalOnClass), before loading any classes.before/after/@AutoConfigureOrder).@Conditional…. Only the configurations whose conditions pass register beans.Key points to cover:
--debug (the CONDITIONS EVALUATION REPORT), or /actuator/conditions. Both show every positive and negative match, and why.Short answer:
@Primary marks the default.@Qualifier("name"), or a custom qualifier annotation, chooses a specific bean.List<T>, Map<String, T>), and pick dynamically (the strategy pattern).ObjectProvider<T> for optional or lazy resolution.@Component
class NotificationRouter {
private final Map<String, NotificationChannel> channels; // bean name → implementation
NotificationRouter(Map<String, NotificationChannel> channels) { this.channels = channels; }
void send(String channel, Message m) { channels.get(channel + "Channel").send(m); }
}
Short answer: Boot first decides the application type:
For a servlet app, the embedded-server auto-configuration tries Tomcat, then Jetty, then Undertow, each with @ConditionalOnClass and @ConditionalOnMissingBean(ServletWebServerFactory.class). The first one present wins, unless you define your own factory.
Common trap: "if no server dependency is found, Boot defaults to Tomcat". It doesn't. With no web stack on the classpath, the application type is NONE, and the app starts without a web server. Tomcat is present only because spring-boot-starter-web includes it.
Short answer: Inject the ApplicationContext and call getBeanDefinitionNames(), or getBeansOfType(X.class) for one type. Operationally, /actuator/beans shows each bean's type, scope, dependencies and the resource that defined it, which is invaluable for "where did this bean come from?".
Short answer: The server (Tomcat, Jetty, Undertow) runs inside your application as a library. SpringApplication creates a ServletWebServerApplicationContext, which obtains a ServletWebServerFactory bean, starts the server, and registers the DispatcherServlet and filters as beans. You configure it with properties (server.port, server.tomcat.threads.max, server.compression.enabled), or a WebServerFactoryCustomizer.
Key points to cover:
server.shutdown=graceful. On Java 21, spring.threads.virtual.enabled=true runs request handling on virtual threads.Learn it in depth → What Is Spring Boot
Short answer: The DI mechanism is the same. What Boot removes is the configuration work around it:
@SpringBootApplication turns on component scanning from the root package.DataSource, ObjectMapper, RestClient.Builder, transaction managers).@ConfigurationProperties binds typed configuration.The result: you write business beans, and inject infrastructure that "just exists".
Short answer: The CLI is a command-line tool, installed with SDKMAN or Homebrew. In Boot 3 it's mainly a project generator: spring init --dependencies=web,data-jpa,actuator --java-version=21 my-service creates a project from Spring Initializr. It also offers spring encodepassword.
Common trap: describing spring run app.groovy for running Groovy scripts. That feature was removed in Spring Boot 3. Projects run through the build tool (./mvnw spring-boot:run) or java -jar.
Short answer: Use @SpringBootApplication(exclude = DataSourceAutoConfiguration.class), excludeName = "…" for classes that may not be on the classpath, or the property spring.autoconfigure.exclude=… (which can vary by profile).
Key points to cover:
Short answer: Yes. Leave out the web starters, or set spring.main.web-application-type=none. The context starts, runs your CommandLineRunners, @Scheduled jobs or message listeners, and the JVM keeps running for as long as non-daemon threads are alive (a Kafka consumer, for example). Typical cases are batch jobs, stream processors and CLI tools.
@SpringBootApplication do internally?Short answer: It combines:
@SpringBootConfiguration: a @Configuration that Boot's test support can find.@EnableAutoConfiguration: the import selector described above.@ComponentScan, with Boot's TypeExcludeFilter and AutoConfigurationExcludeFilter, so auto-configuration classes aren't picked up twice by scanning.@SpringBootApplication's attributes (exclude, scanBasePackages, proxyBeanMethods) delegate to those annotations.
Short answer: It declares its bean method with @ConditionalOnMissingBean. Your configuration is processed before auto-configurations, so by the time the condition is evaluated your bean is already registered. The condition fails, and the auto-configured bean is skipped.
@AutoConfiguration
public class ObjectMapperAutoConfig {
@Bean
@ConditionalOnMissingBean // defaults to the method's return type
ObjectMapper objectMapper() { return JsonMapper.builder().findAndAddModules().build(); }
}
Key points to cover:
@ConditionalOnMissingBean in user configuration is unreliable, because the ordering isn't guaranteed. Use it only inside auto-configuration classes.Short answer: Yes. Exclude spring-boot-starter-tomcat from the web starter, and add spring-boot-starter-jetty or spring-boot-starter-undertow. For fine control, define your own ServletWebServerFactory bean (for example, a TomcatServletWebServerFactory with custom connectors). To deploy to an external server instead, package a WAR and extend SpringBootServletInitializer.
Short answer:
@SpringBootApplication.@Component, @Service, @Repository, @Controller/@RestController.@Configuration, @Bean, @ConfigurationProperties, @Value, @Profile, @Conditional….@RequestMapping and its shortcuts, @PathVariable, @RequestParam, @RequestBody, @Valid, @RestControllerAdvice, @ExceptionHandler.@Entity, @Transactional, @Query.@EnableScheduling + @Scheduled, @EnableAsync + @Async, @EnableCaching + @Cacheable.@SpringBootTest, @WebMvcTest, @DataJpaTest, @MockitoBean.Q: How do you write your own auto-configuration (for a company starter)?
A: Create a @AutoConfiguration class with conditional beans and a @ConfigurationProperties class, list it in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports, and publish it as acme-spring-boot-starter. Test it with ApplicationContextRunner.
Q: What's the difference between @Configuration and @AutoConfiguration?
A: @AutoConfiguration (Boot 2.7+) is a @Configuration(proxyBeanMethods = false) that's meant to be loaded through the imports file, not component scanning, and it supports before/after ordering attributes.
Q: Why does my @Bean override not take effect?
A: Common causes:
The conditions report shows which one applies.
Q: How do you speed up Spring Boot startup?
A: Reduce the classpath and the auto-configurations you don't need, and avoid heavy @PostConstruct work. Consider spring.main.lazy-initialization=true for development, Class Data Sharing / AOT caches, or GraalVM native images for serverless workloads.