Auto-configuration, starters, embedded server — what makes Spring Boot fast to use.
Published September 21, 2026
The Spring Framework is Java's most widely used application framework. Its core is a dependency-injection container that creates your objects and wires them together, plus modules for web APIs, data access, security, messaging and more. Classic Spring was powerful but slow to start with: you chose compatible library versions, wrote configuration for each piece, and deployed a WAR file into an external application server.
Spring Boot is a layer on top of Spring that removes that setup work. It makes sensible default choices for you ("convention over configuration"), and gets out of the way when you need something different. A production-ready REST service becomes a single class, a dependency list and a runnable JAR.
A starter is one dependency that brings a coherent, version-tested set of libraries for one purpose:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.1</version> <!-- manages versions of everything below -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <!-- Spring MVC + Jackson + embedded Tomcat -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId> <!-- MongoDB driver + Spring Data -->
</dependency>
</dependencies>
You no longer pick individual versions of Jackson, Tomcat and Hibernate and hope they're compatible. Boot's dependency management (the parent POM or BOM) pins versions that are tested together. That's also why you usually omit <version> on Boot-managed dependencies.
When the application starts, Boot looks at what's on the classpath, which beans you've already defined, and your properties, and registers the beans you'd almost certainly need. With the MongoDB starter present and a spring.data.mongodb.uri set, a MongoClient and MongoTemplate simply exist, ready to inject.
Each auto-configuration is guarded by conditions:
@AutoConfiguration
@ConditionalOnClass(MongoClient.class) // only if the driver is on the classpath
public class MongoAutoConfiguration {
@Bean
@ConditionalOnMissingBean // only if YOU haven't defined one
public MongoClient mongo(MongoProperties props) { ... }
}
That @ConditionalOnMissingBean is the key design idea: your own bean always wins. Define your own MongoClient (or ObjectMapper, or DataSource) and Boot backs off. Start the app with --debug to print the conditions evaluation report, which lists which auto-configurations applied and why. It's the first thing to check when "Boot configured something I didn't expect". The mechanism in detail is covered in Auto-Configuration Mechanism.
Web applications embed Tomcat (or Jetty or Undertow) inside the application:
./mvnw package
java -jar target/orders-service-1.0.jar # starts the web server on port 8080
One artifact runs the same way on a laptop, in CI and in a container, which makes Docker and cloud deployment straightforward. Boot's layered JARs and buildpack support make container images small and quick to rebuild.
Settings live outside the code, in application.yml or application.properties, and can be overridden by environment variables, command-line arguments or config servers, in a defined priority order:
server:
port: 8081
spring:
data:
mongodb:
uri: ${MONGODB_URI:mongodb://localhost:27017/orders} # env var with a local default
app:
payments:
timeout: 3s
Bind a group of settings to a typed, validated object instead of scattering @Value annotations:
@ConfigurationProperties(prefix = "app.payments")
@Validated
public record PaymentProperties(@NotNull Duration timeout) {}
Profiles (application-dev.yml, application-prod.yml, activated with spring.profiles.active=prod) switch whole sets of configuration between environments. Secrets belong in environment variables or a secret manager, never in committed files.
spring-boot-starter-actuator adds operational endpoints: /actuator/health (for load balancers and Kubernetes probes), /actuator/metrics and /actuator/prometheus (via Micrometer), /actuator/info, and more. Expose only what you need, and secure the rest. Some endpoints (env, heapdump) reveal sensitive details.
@SpringBootApplication
public class OrdersApplication {
public static void main(String[] args) {
SpringApplication.run(OrdersApplication.class, args);
}
}
@RestController
@RequestMapping("/api/v1/orders")
class OrderController {
private final OrderService service;
OrderController(OrderService service) { this.service = service; } // injected automatically
@GetMapping("/{id}")
OrderDto get(@PathVariable String id) { return service.find(id); }
}
@SpringBootApplication combines three annotations:
@SpringBootConfiguration (a @Configuration): this class can declare beans.@EnableAutoConfiguration: turn on the conditional auto-configuration described above.@ComponentScan: find @Component, @Service, @Repository and @Controller classes in this class's package and its sub-packages. Put the main class in your root package. Classes outside that tree are silently not found, which is a common beginner puzzle.SpringApplication.run creates the application context and loads configuration (files, environment, arguments).META-INF/spring/…AutoConfiguration.imports) are evaluated, and those whose conditions pass add their beans.ApplicationRunner / CommandLineRunner beans run here.| Spring Framework | Spring Boot | |
|---|---|---|
| What it is | The core container, MVC, data and security modules | Opinionated setup on top of Spring |
| Configuration | You configure each piece explicitly | Auto-configured defaults, overridden when needed |
| Dependencies | Choose compatible versions yourself | Starters with managed versions |
| Deployment | Traditionally a WAR in an external server | Executable JAR with an embedded server |
| Operations | Add your own | Actuator health, metrics, info |
Boot doesn't replace Spring. Every Boot app is a Spring app, and everything you learn about beans, dependency injection, transactions and MVC applies directly.
Q: What does @SpringBootApplication do?
A: It combines @SpringBootConfiguration (a configuration class), @EnableAutoConfiguration (conditional default beans based on the classpath, existing beans and properties) and @ComponentScan (register annotated classes in the main class's package and sub-packages).
Q: How do you override something Boot auto-configured?
A: Usually by setting a property (for example server.port, spring.jackson.*). For deeper changes, define your own bean of that type, and auto-configurations marked @ConditionalOnMissingBean back off. You can also exclude an auto-configuration entirely with @SpringBootApplication(exclude = …).
Q: How do you find out why a bean was or wasn't auto-configured?
A: Run with --debug, or logging.level.org.springframework.boot.autoconfigure=DEBUG, to print the conditions evaluation report. Or use the Actuator conditions endpoint, which lists matched and unmatched auto-configurations with the reasons.
Q: What is the order of precedence for configuration properties?
A: Roughly, from highest to lowest: command-line arguments, then Java system properties, then OS environment variables, then profile-specific config files, then the default application.yml/properties, then @PropertySource and defaults. The same property set in a higher source overrides the lower ones, which is how one JAR runs with different settings in each environment.
Q: Why package as an executable JAR instead of a WAR? A: The JAR contains the app, its dependencies and the web server, so it runs anywhere with a JVM using a single command. There's no separately managed application server whose version and configuration can drift. It's ideal for containers and cloud platforms. WAR deployment is still supported for organizations that run shared application servers.