Spring Boot is the dominant Java application framework. It packages Spring Framework with sensible defaults, embedded servers, and dependency starters that turn "build a web application" from a hundred lines of XML into a single annotation. Most modern Java backend code runs on Spring Boot or something close to it.
This page covers the core concepts — the parts you need to understand to use Spring Boot effectively, not the encyclopedic catalog of every annotation.
Spring Framework provides:
Spring Boot adds:
The trade-off: Spring Boot's "magic" auto-configuration is convenient but can be opaque when something goes wrong. Understanding what Spring Boot is doing is necessary for non-trivial debugging.
A Spring Boot application starts from a class with @SpringBootApplication:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@SpringBootApplication combines:
@SpringBootConfiguration (Spring Boot's @Configuration)@EnableAutoConfiguration (the magic)@ComponentScan (find beans starting from this package)By convention, @SpringBootApplication lives at the top of the package hierarchy; component scanning finds everything underneath.
A Spring "bean" is an object managed by the IoC container. Three ways to declare:
@Component family on a class@Component
public class OrderService { /* ... */ }
@Service // semantic alias for @Component
@Repository // for data access
@Controller // for web controllers
@RestController // controller + @ResponseBody
The container finds these via @ComponentScan. Annotated classes become beans automatically.
@Bean on methods in a @Configuration class@Configuration
public class AppConfig {
@Bean
public DataSource dataSource() {
return new HikariDataSource();
}
}
Useful for creating beans from third-party code (no annotations available) or for conditional bean creation.
@SpringBootApplication itselfThe application class is also a @Configuration class; you can declare @Bean methods directly on it for small applications.
Inject dependencies via constructor (preferred):
@Service
public class OrderService {
private final OrderRepository repository;
private final NotificationService notifications;
public OrderService(OrderRepository repository, NotificationService notifications) {
this.repository = repository;
this.notifications = notifications;
}
}
The container finds the matching beans and passes them in. final fields make the dependencies clearly required.
Field injection (@Autowired on a field) works but is discouraged: harder to test, hides dependencies, prevents final fields.
The signature feature. Based on what's on the classpath, Spring Boot configures things automatically:
spring-boot-starter-web? Configure embedded Tomcat, Spring MVC, Jackson.spring-boot-starter-data-jpa? Configure Hibernate, transaction management, JPA repositories.spring-boot-starter-actuator? Configure health endpoints, metrics, info.Each starter brings a transitive dependency tree plus the auto-configuration classes that wire it up.
You can:
application.properties / application.yaml@Bean methods that Spring Boot uses instead of its defaultsExternal configuration via application.properties:
server.port=8080
spring.datasource.url=jdbc:postgresql://localhost/mydb
spring.datasource.username=app
logging.level.org.springframework=INFO
Inject configuration with @Value (simple) or @ConfigurationProperties (typed):
@ConfigurationProperties(prefix = "app.email")
public record EmailConfig(String host, int port, String username, String password) {}
Configuration profiles allow environment-specific settings:
application.properties
application-dev.properties
application-prod.properties
Activate a profile with --spring.profiles.active=prod.
REST endpoints with @RestController:
@RestController
@RequestMapping("/api/orders")
public class OrderController {
private final OrderService service;
public OrderController(OrderService service) {
this.service = service;
}
@GetMapping("/{id}")
public Order get(@PathVariable String id) {
return service.findById(id);
}
@PostMapping
public Order create(@RequestBody @Valid CreateOrderRequest request) {
return service.create(request);
}
}
Methods become endpoints; parameters are bound from path, query, headers, or body.
@Repository interfaces extending JpaRepository:
public interface OrderRepository extends JpaRepository<Order, String> {
List<Order> findByStatus(OrderStatus status);
}
Spring Data implements the interface at runtime. Method names are parsed into queries (findByStatus → WHERE status = ?).
For complex queries, @Query annotations or QueryDSL.
@SpringBootTest loads the full application context:
@SpringBootTest
class OrderServiceTest {
@Autowired
OrderService service;
@Test
void shouldCreateOrder() {
Order order = service.create(...);
assertThat(order).isNotNull();
}
}
For faster tests, slices like @WebMvcTest (controller layer only) or @DataJpaTest (data layer only) load a smaller context.
@MockBean replaces a real bean with a Mockito mock for tests.
The fundamentals above cover ~80% of typical Spring Boot usage. Beyond that:
@SpringBootTest for everything. Slow; use slices when possible.application.properties; profile-specific files; environment variables.