Mastering Advanced Spring Boot Starter Configurations: 4 Essential Techniques
This article walks through four advanced Spring Boot Starter design patterns—Customizer, Enable/ConditionalOnProperty, SPI file migration, and AOP interception—showing concrete code examples, the reasoning behind each approach, and practical tips for learning and applying these techniques.
Continuing the "Learning Open‑Source Design" series, this piece focuses on several advanced configurations that can be added to a Spring Boot Starter component after the basic functionality is in place. The author first recaps the three-step starter creation process (defining a *XXXProperties* class, initializing core business logic in an *XXXAutoConfiguration* class, and exposing a *spring.factories* file) and then introduces four higher‑level design patterns.
4.1 Customizer pattern for extensible configuration
The Customizer pattern provides an extension point that allows downstream projects to modify a component’s configuration objects. Using the MyBatis starter as an example, the author shows the functional interface
@FunctionalInterface public interface ConfigurationCustomizer { void customize(Configuration configuration); }and the code that iterates over injected customizers to apply them before the SqlSessionFactoryBean is set.
private void applyConfiguration(SqlSessionFactoryBean factory) {
MybatisProperties.CoreConfiguration coreConfiguration = this.properties.getConfiguration();
Configuration configuration = null;
if (coreConfiguration != null || !StringUtils.hasText(this.properties.getConfigLocation())) {
configuration = new Configuration();
}
if (configuration != null && coreConfiguration != null) {
coreConfiguration.applyTo(configuration);
}
if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) {
for (ConfigurationCustomizer customizer : this.configurationCustomizers) {
customizer.customize(configuration);
}
}
factory.setConfiguration(configuration);
}4.2 Enable mode with ConditionalOnProperty
By defining an annotation that imports an auto‑configuration class, a starter can be toggled on or off. The RocketMQ starter example defines @EnableRocketMQ and then uses @ConditionalOnProperty inside the auto‑configuration to create beans only when specific properties are present.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(RocketMQAutoConfiguration.class)
public @interface EnableRocketMQ {}
@Bean
@ConditionalOnClass(DefaultMQProducer.class)
@ConditionalOnMissingBean(DefaultMQProducer.class)
@ConditionalOnProperty(prefix = "spring.rocketmq", value = {"nameServer", "producer.group"})
public DefaultMQProducer mqProducer(RocketMQProperties rocketMQProperties) {
// ... omitted ...
return producer;
}4.3 SPI declaration file migration (Spring Boot 2.7+)
Older starters used spring.factories to register auto‑configuration classes. Starting with Spring Boot 2.7, this file is deprecated in favor of the
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.importsfile, which lists fully‑qualified configuration class names. The WxJava mini‑app starter is shown as an example, with the import file containing
com.binarywang.spring.starter.wxjava.miniapp.config.WxMaAutoConfiguration.
4.4 AOP‑based interception for automatic enhancement
Some starters need to add cross‑cutting behavior. The author demonstrates a rate‑limiting starter that defines a custom @RateLimit annotation and an @Aspect that intercepts methods annotated with it. The aspect checks the limit via a service and either proceeds or throws a RateLimitException. The auto‑configuration imports the aspect and related beans.
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RateLimit {
Mode mode() default Mode.TIME_WINDOW;
int rate();
// ... omitted ...
}
@Aspect
@Component
@Order(0)
public class RateLimitAspectHandler {
private final RateLimiterService rateLimiterService;
private final RuleProvider ruleProvider;
@Around("@annotation(rateLimit)")
public Object around(ProceedingJoinPoint joinPoint, RateLimit rateLimit) throws Throwable {
Rule rule = ruleProvider.getRateLimiterRule(joinPoint, rateLimit);
Result result = rateLimiterService.isAllowed(rule);
if (!result.isAllow()) {
// ... omitted ...
throw new RateLimitException("Too Many Requests", result.getExtra(), rule.getMode());
}
return joinPoint.proceed();
}
}
@Configuration
@ConditionalOnProperty(prefix = RateLimiterProperties.PREFIX, name = "enabled", havingValue = "true")
@AutoConfigureAfter(RedisAutoConfiguration.class)
@EnableConfigurationProperties(RateLimiterProperties.class)
@Import({RateLimitAspectHandler.class, RateLimitExceptionHandler.class})
public class RateLimiterAutoConfiguration {
// ... omitted ...
}The author concludes that mastering these four patterns—Customizer, Enable/ConditionalOnProperty, the new SPI import mechanism, and AOP interception—significantly improves a developer’s ability to design flexible, reusable Spring Boot Starters.
Learning approach
Beyond the technical details, the article suggests a systematic learning method: read official documentation, study open‑source starter projects on GitHub (e.g., MyBatis, RocketMQ, WxJava, ratelimiter), practice by building small starter prototypes, and eventually create your own starter to solidify the concepts.
By following this workflow, readers can transition from basic starter creation to advanced, production‑ready designs.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Ubiquitous Tech
A ubiquitous public account for pirate enthusiasts, regularly sharing curated experiences, tech learning, and growth insights. Currently publishing articles on AI RAG customer service, AI MCP technology, and open-source design. Personal free Knowledge Planet: Awakening New World Programmer.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
