Starters
A starter is a curated set of dependencies you add as a single coordinate instead of hunting down every individual jar and matching its version. spring-boot-starter-web, for instance, brings Spring MVC, an embedded Tomcat, Jackson, and validation in one line. Starters are the front door to Spring Boot’s auto-configuration: adding one puts the right libraries on the classpath, and auto-config does the wiring.
What a starter actually is
A starter is mostly an empty jar — a pom.xml with no code — that declares transitive dependencies. Adding spring-boot-starter-web pulls in everything you need for a web application, transitively. Starters follow a naming convention: official ones are spring-boot-starter-*; third-party ones use their own prefix, like acme-spring-boot-starter.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Notice there is no <version>. That is the second half of the story: dependency management.
Dependency management and the BOM
Spring Boot publishes a BOM (Bill of Materials) named spring-boot-dependencies that pins compatible versions for hundreds of libraries. When your project inherits or imports it, you declare dependencies without versions and Spring Boot supplies a tested, consistent set — eliminating version conflicts between, say, Jackson and Spring.
The simplest way to get the BOM is to inherit from spring-boot-starter-parent:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.0</version>
<relativePath/>
</parent>
The parent also configures the compiler for Java 17+, sets UTF-8 encoding, and pre-configures plugins like spring-boot-maven-plugin.
If your project already has its own parent, import the BOM in dependencyManagement instead:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.5.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Tip: To override a managed version (for example, to bump a single library), set the corresponding property the BOM defines — e.g.
<jackson-bom.version>2.18.0</jackson-bom.version>— rather than pinning a<version>on the dependency itself. This keeps the rest of the dependency set coherent.
Common starters
| Starter | What it brings |
|---|---|
spring-boot-starter-web | Spring MVC, embedded Tomcat, Jackson JSON, validation — build REST APIs and MVC apps |
spring-boot-starter-data-jpa | Spring Data JPA, Hibernate, JDBC, transaction management |
spring-boot-starter-security | Spring Security: filter chain, authentication, authorization |
spring-boot-starter-validation | Jakarta Bean Validation API + Hibernate Validator |
spring-boot-starter-test | JUnit 5, Mockito, AssertJ, Spring Test, JSONassert (test scope) |
spring-boot-starter-actuator | Production endpoints: health, metrics, info, env over HTTP/JMX |
A minimal REST + persistence service typically needs just a few:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Note: Some starters are “technical” rather than feature-based.
spring-boot-starteris the core starter (used by others);spring-boot-starter-loggingprovides the default Logback setup; and you swapspring-boot-starter-tomcatforspring-boot-starter-jettyor-undertowto change the embedded server.
Authoring a custom starter
When you build a reusable library — say, an internal client for a shared service — you can ship it as a starter so consumers get it working with one dependency. The convention splits the work into two modules:
- An autoconfigure module (
acme-spring-boot-autoconfigure) containing the@AutoConfigurationclasses,@ConfigurationProperties, and theAutoConfiguration.importsfile. - A thin starter module (
acme-spring-boot-starter) with no code that depends on the autoconfigure module plus any required libraries.
Warning: Naming matters. Use
acme-spring-boot-starter, notspring-boot-starter-acme— thespring-boot-starter-prefix is reserved for starters maintained by the Spring Boot team. Mixing it up causes confusion about provenance and support.
The autoconfigure module registers its config class:
# acme-spring-boot-autoconfigure/src/main/resources/
# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.acme.autoconfigure.AcmeClientAutoConfiguration
@AutoConfiguration
@ConditionalOnClass(AcmeClient.class)
@EnableConfigurationProperties(AcmeProperties.class)
public class AcmeClientAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public AcmeClient acmeClient(AcmeProperties props) {
return new AcmeClient(props.baseUrl(), props.apiKey());
}
}
The starter module is just dependencies:
<project>
<artifactId>acme-spring-boot-starter</artifactId>
<dependencies>
<dependency>
<groupId>com.acme</groupId>
<artifactId>acme-spring-boot-autoconfigure</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.acme</groupId>
<artifactId>acme-client</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>
Consumers then add a single dependency, and the conditional beans in your autoconfigure module wire themselves up — backing off via @ConditionalOnMissingBean if the consumer defines their own.
Best Practices
- Inherit
spring-boot-starter-parentfor new projects; importspring-boot-dependencieswhen you already have a parent. - Declare Spring-managed dependencies without versions and let the BOM decide.
- Override a managed version through the documented BOM property, not a hard-coded
<version>. - Pick the smallest set of starters that covers your features; remove ones you no longer use to keep the classpath lean.
- For custom starters, follow the two-module split and the
*-spring-boot-starternaming convention.