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-web
、spring-boot-starter-data-jpa
etc. 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-starter
Format
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
- use
spring-boot-starter
As 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
@ConditionalOnMissingBean
Avoid 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!