SoFunction
Updated on 2025-04-14

Introduction to 6 ways to customize starters in SpringBoot

1. What is SpringBoot Starter

In the SpringBoot ecosystem, starter is a special dependency, which can automatically assemble related components and simplify project configuration. Officially provided many starters, such asspring-boot-starter-webspring-boot-starter-data-jpaetc. But in actual business, we often need to develop our own starter to encapsulate common functions, realize one-time development and multiple reuse.

The core value of a custom starter is:

  • Encapsulate complex configuration logic for use out of the box
  • Unify the usage specifications of technical components to avoid the flooding of "wheels"
  • Improve development efficiency and reduce duplicate code
  • Easy to manage and upgrade and maintain the version uniformly

This article will introduce 6 different custom starter development methods in detail.

2. Method 1: Basic configuration method

This is the easiest way to starter development, by creating a configuration class with @Configuration annotation, using the @Bean method to define the components that need to be injected.

Implementation steps

Create a Maven project: Namedxxx-spring-boot-starterFormat

Add dependencies

<dependencies>
    <dependency>
        <groupId></groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
</dependencies>

Create a configuration class

@Configuration
public class SimpleServiceAutoConfiguration {
    
    @Bean
    public SimpleService simpleService() {
        return new SimpleServiceImpl();
    }
}

Create an automatic configuration file:existresources/META-INF/Added in:

=\

How to use

When using it, just add dependencies to the project:

<dependency>
    <groupId></groupId>
    <artifactId>simple-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>

Pros and cons analysis

advantage

  • Simple to implement, easy to get started
  • Suitable for simple packaging of functional components

shortcoming

  • Customized configuration is not supported
  • Unable to selectively assemble according to conditions
  • The function is too simple, and the applicable scenarios are limited

Applicable scenarios: Suitable for packaging simple tool classes or functional components that do not require external configuration.

3. Method 2: Conditional assembly method

Through SpringBoot's conditional assembly mechanism, it is possible to determine whether to enable configuration starter based on specific conditions.

Implementation steps

Create a Maven projectSame as above

Create a configuration class, add conditional annotations:

@Configuration
@ConditionalOnClass()
public class RedisServiceAutoConfiguration {
    
    @Bean
    @ConditionalOnMissingBean
    public RedisService redisService() {
        return new RedisServiceImpl();
    }
    
    @Bean
    @ConditionalOnProperty(prefix = "", name = "enabled", havingValue = "true")
    public RedisCacheManager redisCacheManager() {
        return new RedisCacheManager();
    }
}

Configure automatic assembly filesSame as above

Conditional annotation description

SpringBoot provides rich conditional annotations:

  • @ConditionalOnClass: When there is a specified class under the classpath
  • @ConditionalOnMissingBean: When no bean is specified in the container
  • @ConditionalOnProperty: When there are specified attributes in the configuration file
  • @ConditionalOnWebApplication: When the application is a web application
  • @ConditionalOnExpression: Conditions based on SpEL expression

Pros and cons analysis

advantage

  • Intelligent assembly to avoid useless component loading
  • You can decide whether to enable the function based on the environment conditions
  • Prevent conflicts with existing beans

shortcoming

  • The configuration logic is complex
  • Debugging and troubleshooting difficulties increase
  • Priority and conflict between conditions need to be considered

Applicable scenarios: Suitable for functional components that need to be optionally enabled according to environmental conditions, such as whether to enable web-related functions based on whether it is a web environment.

4. Method 3: Attribute binding method

Implement custom configuration starter through @ConfigurationProperties, which supports reading parameters from configuration files.

Implementation steps

Create attribute class

@ConfigurationProperties(prefix = "")
@Data
public class ServiceProperties {
    /**
      * Whether to enable the service
      */
    private boolean enabled = true;
    
    /**
      * Service URL
      */
    private String url = "http://localhost:8080";
    
    /**
      * Connection timeout
      */
    private int timeout = 3000;
}

Create an automatic configuration class

@Configuration
@EnableConfigurationProperties()
@ConditionalOnProperty(prefix = "", name = "enabled", havingValue = "true", matchIfMissing = true)
public class ExampleServiceAutoConfiguration {
    
    @Autowired
    private ServiceProperties properties;
    
    @Bean
    @ConditionalOnMissingBean
    public ExampleService exampleService() {
        return new ExampleServiceImpl((), ());
    }
}

Configuration metadata prompts:createMETA-INF/

{
  "properties": [
    {
      "name": "",
      "type": "",
      "description": "Whether to enable example service.",
      "defaultValue": true
    },
    {
      "name": "",
      "type": "",
      "description": "Service URL.",
      "defaultValue": "http://localhost:8080"
    },
    {
      "name": "",
      "type": "",
      "description": "Connection timeout in milliseconds.",
      "defaultValue": 3000
    }
  ]
}

Pros and cons analysis

advantage

  • Supports reading parameters from configuration files to achieve flexible configuration
  • The configuration item has metadata prompts, and the user experience is good
  • Supports configuration checksum default values

shortcoming

  • Increased development workload
  • Need to maintain configuration metadata
  • Management is complicated when there are too many configuration items

Applicable scenarios: Suitable for functional components that need to be customized through external configurations, such as various client and connection pool configurations.

5. Method 4: Fully automatic configuration method

Combined with the previous method, a complete automatic configuration starter is implemented, including conditional assembly, property binding and multi-component configuration.

Implementation steps

Create multiple components

// Core service interfacepublic interface ComplexService {
    String process(String input);
}

// Implementation classpublic class ComplexServiceImpl implements ComplexService {
    private final String endpoint;
    private final int timeout;
    
    public ComplexServiceImpl(String endpoint, int timeout) {
         = endpoint;
         = timeout;
    }
    
    @Override
    public String process(String input) {
        // Implementation logic        return "Processed: " + input;
    }
}

// Auxiliary componentspublic class ServiceHelper {
    public void assist() {
        // Auxiliary function implementation    }
}

Create attribute class

@ConfigurationProperties(prefix = "")
@Data
public class ComplexServiceProperties {
    private boolean enabled = true;
    private String endpoint = "";
    private int timeout = 5000;
    private AdvancedConfig advanced = new AdvancedConfig();
    
    @Data
    public static class AdvancedConfig {
        private boolean cacheEnabled = false;
        private int cacheSize = 100;
    }
}

Create an automatic configuration class

@Configuration
@EnableConfigurationProperties()
@ConditionalOnProperty(prefix = "", name = "enabled", havingValue = "true", matchIfMissing = true)
public class ComplexServiceAutoConfiguration {
    
    @Autowired
    private ComplexServiceProperties properties;
    
    @Bean
    @ConditionalOnMissingBean
    public ComplexService complexService() {
        return new ComplexServiceImpl(
            (), 
            ()
        );
    }
    
    @Bean
    @ConditionalOnProperty(prefix = "", name = "cache-enabled", havingValue = "true")
    public CacheManager cacheManager() {
        return new SimpleCacheManager(().getCacheSize());
    }
    
    @Bean
    public ServiceHelper serviceHelper() {
        return new ServiceHelper();
    }
}

Add automatic assembly files:existMETA-INF/Add configuration in

Pros and cons analysis

advantage

  • Complete functions and support complex scenarios
  • Component design, supporting conditional assembly
  • Flexible configuration options

shortcoming

  • High complexity
  • Dependencies between multiple components need to be considered

Applicable scenarios: Suitable for complex enterprise-level functional components, such as distributed transactions, security authentication, and other scenarios where multiple components work together.

6. Method 5: Enable mode

By customizing @Enable annotation, users can actively enable specific features.

Implementation steps

Create functional interfaces and implement classes

public interface FeatureService {
    void execute();
}

public class FeatureServiceImpl implements FeatureService {
    @Override
    public void execute() {
        // Implementation logic    }
}

Create @Enable annotation

@Retention()
@Target()
@Import()
public @interface EnableFeature {
    /**
      * Mode settings
      */
    Mode mode() default ;
    
    enum Mode {
        SIMPLE, ADVANCED
    }
}

Create a configuration class

@Configuration
public class FeatureConfiguration implements ImportAware {
    
    private  mode;
    
    @Override
    public void setImportMetadata(AnnotationMetadata importMetadata) {
        Map<String, Object> attributes = (
                ());
         = () ("mode");
    }
    
    @Bean
    public FeatureService featureService() {
        if (mode == ) {
            return new SimpleFeatureServiceImpl();
        } else {
            return new AdvancedFeatureServiceImpl();
        }
    }
}

How to use

Use the @Enable annotation to enable the function in the main application class:

@SpringBootApplication
@EnableFeature(mode = )
public class MyApplication {
    public static void main(String[] args) {
        (, args);
    }
}

Pros and cons analysis

advantage

  • Explicitly enable the function, use intention is clear
  • Supports customization function through annotation parameters
  • Can be used in conjunction with automatic configuration

shortcoming

  • Users need to actively add annotations
  • Not exactly in line with SpringBoot's philosophy of using out of the box
  • Increase user burden

Applicable scenarios: Suitable for optional features or functional components with multiple usage modes, such as specific integration solutions or optional feature enhancements.

7. Method 6: Modular and Combination Starter

By splitting functional modules, a composable starter system is realized, and users can introduce the required functions as needed.

Implementation steps

Create basic modules

myproject-spring-boot-starter (parent module)
├── myproject-core-spring-boot-starter (core function)
├── myproject-web-spring-boot-starter (Web function)
├── myproject-cache-spring-boot-starter (cache function)
└── myproject-security-spring-boot-starter (safety function)

Core module implementation

// In the core module@Configuration
@ConditionalOnClass()
public class CoreAutoConfiguration {
    
    @Bean
    @ConditionalOnMissingBean
    public CoreService coreService() {
        return new CoreServiceImpl();
    }
}

Functional module implementation

// In the web module@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass()
public class WebAutoConfiguration {
    
    @Autowired
    private CoreService coreService;
    
    @Bean
    public WebService webService() {
        return new WebServiceImpl(coreService);
    }
}

Dependency management

<dependency>
    <groupId></groupId>
    <artifactId>myproject-core-spring-boot-starter</artifactId>
    <version>${}</version>
</dependency>

Pros and cons analysis

advantage

  • Modular functions, introduced on demand
  • Reduce unnecessary dependencies
  • Easy to collaboratively develop teams
  • Comply with the principle of single responsibility

shortcoming

  • Complex dependency management between modules
  • Difficulty in maintaining version consistency
  • Increased development and testing workload

Applicable scenarios: Suitable for large-scale projects or platform-based applications, and different functional combinations need to be selected according to different business scenarios.

8. Comparison and selection suggestions for various methods

method Difficulty to achieve flexibility Configurability Applicable scenarios
Basic configuration method ★☆☆☆☆ ★★☆☆☆ ★☆☆☆☆ Simple tool package
Conditional assembly method ★★☆☆☆ ★★★☆☆ ★★☆☆☆ Environmentally sensitive functions
Attribute binding method ★★★☆☆ ★★★★☆ ★★★★★ Configurable components
Fully automatic configuration ★★★★☆ ★★★★★ ★★★★★ Enterprise-level complex functions
Enable mode ★★★☆☆ ★★★★☆ ★★★☆☆ Optional functional components
Modular combination method ★★★★★ ★★★★★ ★★★★★ Large platform-level application

9. Custom starter development best practices

1. Naming Specifications

  • Unofficial starter naming:xxx-spring-boot-starter
  • Official starter name:spring-boot-starter-xxx

2. Dependency management

  • usespring-boot-starterAs a basic dependency
  • Avoid introducing unnecessary transitive dependencies
  • Clearly declare the scope of version compatibility

3. Configuration design

  • Use reasonable configuration prefixes to avoid conflicts
  • Provide reasonable default values
  • Write complete configuration metadata and provide IDE prompts

4. Conditional Assembly

  • Use conditional annotations reasonably to avoid unnecessary component loading
  • use@ConditionalOnMissingBeanAvoid overwriting user-defined beans
  • Considering a combination of various environmental conditions

5. Error handling

  • Provide clear error prompts
  • Implement a reasonable downgrade strategy
  • Provides diagnostic and self-test functions

6. Documentation

  • Write detailed usage documents
  • Provide configuration examples
  • Explain how to integrate with other components

10. Summary

Custom starter is an important expansion mechanism in the SpringBoot ecosystem. Developers can choose the right way to implement their starter according to different needs scenarios. From simple basic configuration methods to complex modular combination methods, each method has its applicable scenarios and advantages and disadvantages.

When developing a custom starter, the following principles should be followed:

  • Follow the concept of agreement over configuration
  • Provide reasonable default values
  • Allows users to customize and override default behaviors
  • Do a good job in error handling and downgrade

This is the article about 6 ways to customize starters in SpringBoot. For more related SpringBoot custom starters, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!