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.
<code>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);
}</code>Spring's
@Autowiredcan 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-diand its
AutowiredProxySPIcome into play.
1. spring‑smart‑di
spring‑smart‑di extends Spring's
@Autowiredmechanism, allowing developers to define custom injection logic. It currently provides two annotations:
@SmartAutowiredand
@AutowiredProxySPI. The article focuses on using
@AutowiredProxySPIfor dynamic switching.
2. Quick Start
Add the Maven dependency:
<code><dependency>
<groupId>io.github.burukeyou</groupId>
<artifactId>spring-smart-di-all</artifactId>
<version>0.2.0</version>
</dependency></code>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.
<code>@EnvironmentProxySPI("${sms.impl}")
public interface SmsService {
}
@BeanAliasName("某腾短信服务")
@Component
public class ASmsService implements SmsService {}
@BeanAliasName("某移短信服务")
@Component
public class BSmsService implements SmsService {}
</code>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.
<code>sms:
impl: 某移短信服务</code>2.3 Using @AutowiredProxySPI
Inject the service just like a regular
@Autowiredfield:
<code>// Dependency injection
@AutowiredProxySPI
private SmsService smsService;</code>Changing the
${sms.impl}value updates the injected proxy in real time without restarting the application.
2.4 Defining Custom Configuration Points
While
@EnvironmentProxySPIreads from environment variables, developers can create custom annotations (e.g.,
@DBProxySPI) to fetch configuration from a database. The custom annotation is marked with
@ProxySPIand points to a factory that implements the retrieval logic.
<code>@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 {}
</code>Project repository: https://github.com/burukeYou/spring-smart-di
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.