Dynamic Service Switching in Spring Boot Using spring‑smart‑di
This article explains how to implement dynamic switching of service implementations in a Spring Boot application by leveraging the spring‑smart‑di library, covering configuration setup, custom annotations, and code examples that enable runtime changes without restarting the service.
0. Background
When a system integrates multiple service providers for the same functionality, developers often need a fast way to switch providers based on availability or pricing. The traditional approach stores each provider implementation and selects the active one via a configuration point (e.g., a database or Nacos), retrieving the current provider each time a request is processed.
For example, a system may integrate several SMS providers and allow users to switch between them dynamically.
Step 1: Configure the current provider, e.g., sms.impl = "某腾短信".
Step 2: In the sending logic, read sms.impl, obtain the corresponding implementation class, and invoke its method.
void sendSmsTouser(Req req) {
// 1. Get the current provider name
String name = get("sms.impl");
// 2. Retrieve the implementation bean
SmsService smsService = springContext.getBean(name);
// 3. Execute the business logic
smsService.sendMsg(req);
}Spring's @Autowired can be extended so that the injected bean automatically follows the configuration, eliminating the need to manually fetch the provider each time. This is where spring-smart-di and its AutowiredProxySPI come into play.
1. spring‑smart‑di
spring‑smart‑di extends Spring's @Autowired mechanism, allowing developers to define custom injection logic. It currently provides two annotations: @SmartAutowired and @AutowiredProxySPI. The article focuses on using @AutowiredProxySPI for dynamic switching.
2. Quick Start
Add the Maven dependency:
<dependency>
<groupId>io.github.burukeyou</groupId>
<artifactId>spring-smart-di-all</artifactId>
<version>0.2.0</version>
</dependency>Enable the feature on a Spring configuration class with @EnableSmartDI.
2.1 @EnvironmentProxySPI Annotation
@EnvironmentProxySPImarks a configuration point that determines how to obtain the concrete implementation class, typically from an environment variable.
@EnvironmentProxySPI("${sms.impl}")
public interface SmsService {
}
@BeanAliasName("某腾短信服务")
@Component
public class ASmsService implements SmsService {}
@BeanAliasName("某移短信服务")
@Component
public class BSmsService implements SmsService {}2.2 Configuring the Active Provider
Specify the active provider in a configuration file (e.g., application.yml); the value can be a bean alias, component name, or fully qualified class name.
sms:
impl: 某移短信服务2.3 Using @AutowiredProxySPI
Inject the service just like a regular @Autowired field:
// Dependency injection
@AutowiredProxySPI
private SmsService smsService;Changing the ${sms.impl} value updates the injected proxy in real time without restarting the application.
2.4 Defining Custom Configuration Points
While @EnvironmentProxySPI reads from environment variables, developers can create custom annotations (e.g., @DBProxySPI) to fetch configuration from a database. The custom annotation is marked with @ProxySPI and points to a factory that implements the retrieval logic.
@Inherited
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@ProxySPI(DbProxyFactory.class) // specify config retrieval logic
public @interface DBProxySPI {
String value();
}
@Component
public class DbProxyFactory implements AnnotationProxyFactory<DBProxySPI> {
@Autowired
private SysConfigMapper sysConfigDao;
@Override
public Object getProxy(Class<?> targetClass, DBProxySPI spi) {
// Retrieve implementation name from DB based on annotation value
String configName = sysConfigDao.getConfig(spi.value());
return springContext.getBean(configName);
}
}
@DBProxySPI("${sms.impl}")
public interface SmsService {}Project repository: https://github.com/burukeYou/spring-smart-di
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.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
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.
