Dynamic Service Provider Switching with Spring-Smart-DI's @AutowiredProxySPI
This tutorial demonstrates how to use Spring-Smart-DI's @AutowiredProxySPI annotation to dynamically switch between multiple service implementations (e.g., SMS providers) at runtime by changing configuration values, without application restarts, using proxy-based injection that resolves the active implementation on each call.
1. spring-smart-di Introduction
spring-smart-diis an innovative extension of Spring's @Autowired annotation that provides custom autowiring logic. It implements two key annotations: @SmartAutowired and @AutowiredProxySPI. This article focuses on @AutowiredProxySPI for dynamic service provider switching.
2. Quick Start
2.1 Add Dependency
Add the following Maven dependency to pom.xml:
<dependency>
<groupId>io.github.burukeyou</groupId>
<artifactId>spring-smart-di-all</artifactId>
<version>0.2.0</version>
</dependency>2.2 Enable Functionality
Annotate a Spring configuration class with @EnableSmartDI to activate the framework.
2.3 @EnvironmentProxySPI Annotation Usage
@EnvironmentProxySPIdefines a configuration point that determines how to retrieve the active implementation class. For example, with two SMS providers:
@EnvironmentProxySPI("${sms.impl}")
public interface SmsService {}
@BeanAliasName("某腾短信服务")
@Component
public class ASmsService implements SmsService {}
@BeanAliasName("某移短信服务")
@Component
public class BSmsService implements SmsService {}The interface is annotated with @EnvironmentProxySPI referencing the property ${sms.impl}. Each implementation gets a @BeanAliasName for identification.
2.4 Configure Active Service Provider
In the configuration file (e.g., YAML), set the active provider using the alias, component name, or fully qualified class name:
sms:
impl: 某移短信服务2.5 @AutowiredProxySPI Injection
Inject the service interface using @AutowiredProxySPI just like @Autowired:
@AutowiredProxySPI
private SmsService smsService;Changing ${sms.impl} takes effect immediately without restart because @AutowiredProxySPI injects a proxy that resolves the current implementation on each invocation.
2.6 Custom Configuration Points
For non-environment configuration sources (e.g., database), create a custom @ProxySPI annotation. Example @DBProxySPI reading from a database:
@Inherited
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@ProxySPI(DbProxyFactory.class)
public @interface DBProxySPI {
String value();
}
@Component
public class DbProxyFactory implements AnnotationProxyFactory<DBProxySPI> {
@Autowired
private SysConfigMapper sysConfigDao;
@Override
public Object getProxy(Class<?> targetClass, DBProxySPI spi) {
String configName = sysConfigDao.getConfig(spi.value());
return springContext.getBean(configName);
}
}
@DBProxySPI("${sms.impl}")
public interface SmsService {}The factory implements AnnotationProxyFactory and uses a mapper to fetch the active implementation name from the database, then returns the corresponding Spring bean.
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.
Java Architect Handbook
Focused on Java interview questions and practical article sharing, covering algorithms, databases, Spring Boot, microservices, high concurrency, JVM, Docker containers, and ELK-related knowledge. Looking forward to progressing together with you.
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.
