Spring Boot is known for its opinionated auto-configuration and rapid setup capabilities. One of the hidden gems of its ecosystem is custom starters β reusable libraries that help you abstract configuration, dependencies, and auto-configuration logic into standalone modules. In this tutorial, we will walk through building custom starters in Spring Boot 3.
Whether you’re building internal tooling or want to reuse boilerplate code across projects, custom starters in Spring Boot 3 are the key to modular, scalable Java development.

π― What is a Spring Boot Starter?
A starter is simply a Maven/Gradle dependency that:
- Includes transitive dependencies.
- Optionally provides auto-configuration logic.
- May expose Spring components like services or configurations.
Spring Boot itself offers many starters like:
spring-boot-starter-web
spring-boot-starter-data-jpa
spring-boot-starter-security
Letβs build our own!
π Project Structure
We will create:
- A custom starter module (e.g.,
kscodes-greeting-starter
) - A demo application that uses it
1 2 3 4 5 6 7 8 |
spring-boot-custom-starter/ βββ kscodes-greeting-starter/ β βββ src/main/java/com/kscodes/springboot/greeting/ βββ greeting-app/ β βββ src/main/java/com/kscodes/springboot/demo/ |
π¦ Step 1: Create the Custom Starter Module
πΉ pom.xml for kscodes-greeting-starter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<project> <groupId>com.kscodes.springboot</groupId> <artifactId>kscodes-greeting-starter</artifactId> <version>1.0.0</version> <packaging>jar</packaging> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> </dependencies> </project> |
β¨ Step 2: Create the Configuration Properties Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package com.kscodes.springboot.greeting; import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "kscodes.greeting") public class GreetingProperties { private String message = "Hello from custom starter!"; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } |
π§ Step 3: Create the AutoConfiguration Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package com.kscodes.springboot.greeting; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.boot.context.properties.EnableConfigurationProperties; @Configuration @EnableConfigurationProperties(GreetingProperties.class) @ConditionalOnProperty(prefix = "kscodes.greeting", name = "enabled", havingValue = "true", matchIfMissing = true) public class GreetingAutoConfiguration { @Bean @ConditionalOnMissingBean public GreetingService greetingService(GreetingProperties properties) { return new GreetingService(properties.getMessage()); } } |
π§Ύ Step 4: Create the Service Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.kscodes.springboot.greeting; public class GreetingService { private final String message; public GreetingService(String message) { this.message = message; } public String greet(String name) { return message + " " + name + "!"; } } |
π Step 5: Register the Auto-Configuration File
In src/main/resources/META-INF/spring.factories
:
1 2 3 4 5 |
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.kscodes.springboot.greeting.GreetingAutoConfiguration |
π§ͺ Step 6: Create a Demo App to Use the Starter
πΉ Add Dependency in greeting-app/pom.xml
1 2 3 4 5 6 7 8 9 |
<dependency> <groupId>com.kscodes.springboot</groupId> <artifactId>kscodes-greeting-starter</artifactId> <version>1.0.0</version> </dependency> |
π§ Step 7: Use in the Application
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package com.kscodes.springboot.demo; import com.kscodes.springboot.greeting.GreetingService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class GreetingApp implements CommandLineRunner { @Autowired private GreetingService greetingService; public static void main(String[] args) { SpringApplication.run(GreetingApp.class, args); } @Override public void run(String... args) { System.out.println(greetingService.greet("Ketan")); } } |
βοΈ Optional: Customize the Message via application.properties
1 2 3 4 5 |
kscodes.greeting.message=Namaste from KSCodes Starter kscodes.greeting.enabled=true |
π‘ Advantages of Using Custom Starters in Spring Boot 3
- Promote code reuse and standardization
- Reduce repetitive configurations
- Ideal for internal enterprise platforms and shared teams
- Perfect for open-source starter kits
You can abstract anything from logging, monitoring, metrics, service discovery clients, internal SDKs, etc.
π§Ή Tips & Best Practices
- Name your starter clearly:
*-starter
- Provide sane defaults using
@ConfigurationProperties
- Use
@ConditionalOn*
annotations for flexibility - Register your
spring.factories
orspring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
in Spring Boot 3.1+
π Conclusion
Creating custom starters in Spring Boot 3 is an elegant way to modularize your configurations and reuse business logic. Whether you’re streamlining internal SDKs or building reusable Spring components, custom starters reduce boilerplate and enhance consistency across teams.
With this guide, you can now start building custom starters in Spring Boot 3 for your own needs or for the developer community.
β Summary
- β
Use
spring-boot-autoconfigure
- β
Create
@ConfigurationProperties
and@Configuration
with conditional beans - β
Register your config in
spring.factories
- β Use it like any other Spring Boot starter