Spring Boot assembles a Spring application from the dependencies, beans, and configuration it can see. Starter dependencies provide a compatible feature set, auto-configuration supplies sensible beans when the application has not supplied its own, and an embedded server lets a web application run as an executable process. Spring Boot 4.1 requires Java 17 or later and Spring Framework 7.0.8 or later.
The goal is not zero configuration. The goal is to begin with a coherent default, then override only the decisions your application actually owns. By the end, you can explain why an auto-configuration matched, replace one default safely, and separate environment configuration from source code.
Spring Boot is an opinionated framework built on top of Spring that simplifies the setup and development of Spring applications. It provides:
package com.example;
import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.context.annotation.*;
// @SpringBootApplication combines:
// @Configuration - Java config class
// @EnableAutoConfiguration - Enable Spring Boot auto-config
// @ComponentScan - Scan for @Component, @Service, etc.
@SpringBootApplication
// Exclude specific auto-configurations if needed:
// @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class Application {
public static void main(String[] args) {
// Customize SpringApplication
SpringApplication app = new SpringApplication(Application.class);
app.setBannerMode(Banner.Mode.OFF); // Disable startup banner
app.run(args);
}
}
// ApplicationRunner: runs code after application starts
@Component
public class StartupRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("Application started successfully!");
// args.getOptionValues("server.port") - access command line args
}
}
Spring profiles allow you to have different configurations for different environments (dev, test, prod):
// Profile-specific beans
@Configuration
public class DataSourceConfig {
@Bean
@Profile("dev")
public DataSource devDataSource() {
// H2 in-memory database for development
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.build();
}
@Bean
@Profile("prod")
public DataSource prodDataSource() {
// MySQL for production
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl("jdbc:mysql://prod-server:3306/mydb");
return ds;
}
}
// Activate profile:
// application.properties: spring.profiles.active=dev
// Command line: java -jar app.jar --spring.profiles.active=prod
// Environment variable: SPRING_PROFILES_ACTIVE=prod
# application-dev.properties (active when profile=dev)
server.port=8080
spring.datasource.url=jdbc:h2:mem:devdb
spring.jpa.hibernate.ddl-auto=create-drop
logging.level.com.example=DEBUG
# application-prod.properties (active when profile=prod)
# server.port=80
# spring.datasource.url=jdbc:mysql://prod-server:3306/mydb
# spring.jpa.hibernate.ddl-auto=validate
# logging.level.com.example=WARN
# Expose only the endpoints required by the operations workflow.
management.endpoints.web.exposure.include=health,info,metrics
management.endpoint.health.show-details=never
management.info.env.enabled=true
# Custom info
info.app.name=My Spring App
info.app.version=1.0.0
info.app.description=A sample Spring Boot application
# Actuator endpoints (after adding spring-boot-starter-actuator):
# GET /actuator/health - Application health status
# GET /actuator/info - Application info
# GET /actuator/metrics - Application metrics
# Keep env, beans, mappings, and detailed health data protected unless an
# authenticated operations workflow explicitly requires them.
Auto-configuration is conditional. A web dependency may trigger MVC infrastructure; a database driver and DataSource settings may trigger database beans. Many conditions back off when you define your own bean, which means customization is usually additive rather than an all-or-nothing switch.
When startup behavior is surprising, run with debug enabled and inspect the condition evaluation report. It shows positive matches, negative matches, and exclusions. Use that evidence before excluding an auto-configuration, because an exclusion can also remove related infrastructure the application still needs.
Keep deploy-specific values outside the packaged application. Properties, YAML, environment variables, command-line arguments, and profile-specific files can contribute configuration with a defined precedence. Store credentials in the deployment platform or secret manager, not in application.properties and never in a tutorial repository.
Profiles select groups of beans or properties, but they should represent meaningful environments or modes rather than every small feature flag. Prefer typed @ConfigurationProperties for a related group of settings; validation then catches missing or malformed values during startup instead of much later in a request.
Actuator exposes operational endpoints such as health and metrics when its starter is present. Expose only endpoints the operations workflow needs, secure sensitive endpoints, and avoid showing complete environment details publicly. A health response should answer whether the instance can serve traffic, not leak its configuration.
An embedded server simplifies packaging but does not remove deployment responsibilities. Configure graceful shutdown, timeouts, forwarded headers, TLS termination, resource limits, and observability for the environment where the process runs.
Try this next
0 of 2 completed
Explore 500+ free tutorials across 20+ languages and frameworks.