spring-smart-di 动态切换接口源

0、背景

一般我们系统同一个功能可能会对接多个服务商,防止某个服务商的服务不可用快速切换或者收费不同需要切换,那我们一般做快速切换逻辑传统无非就是先将每个服务商实现,然后在配置点(数据库或者nacos)配置当前正在使用的服务商。然后每次执行的时候从配置点获取当前正在使用的服务商,然后去执行该服务商的业务逻辑。

比如系统接入了多个短信服务商,然后用户可以动态的切换不同的服务商,

如果让我们手写会如何实现。

  • 第一步先在某个位置(不管是nacos还是数据库)配置当前使用的服务商的对应值比如 sms.impl = "某腾短信"

  • 第二步,在代码里执行发短信的时候,手动获取该sms.impl对应的服务商的实现类,伪代码可能如下

java 复制代码
void sendSmsTouser(Req req){
	 // 1、获取当前使用的服务商
	 String name = get("sms.impl");
	// 2、获取对应的实现类
	 SmsService smsService = springContext.getBean(name);
	// 3、使用smsService执行具体业务逻辑
	smsService.sendMsg(req)
}

这时有一个想法就是 spring的@Autowired注解在注入的时候可以自动根据在配置点配置的实现类去注入,并且当配置变了,注入的实现类也会改变,这样就跟正常写代码一样不再需要去关注当前使用的实现类。这时spring-smart-di 的 AutowiredProxySPI 应运而生。

1、spring-smart-di

它是一个对spring@Autowired注解的扩展,能够自定义用户自己的Autowired注入逻辑,目前实现了两个功能分别是 @SmartAutowired @AutowiredProxySPI 注解,我们这里要使用的便是AutowiredProxySPI 去实现我们的动态切换逻辑。

假设对接了多个短信服务商,下面以一个快速开始案例去看看如何使用 AutowiredProxySPI 如何实现动态切换

2、快速开始

引入依赖

xml 复制代码
    <dependency>
        <groupId>io.github.burukeyou</groupId>
        <artifactId>spring-smart-di-all</artifactId>
        <version>0.1.1</version>
    </dependency>

然后在Spring配置类上标记 @EnableSmartDI 注解 启用功能

2.1 @EnvironmentProxySPI注解

@EnvironmentProxySPI代表的是一个配置点,用来配置怎么获取具体实现类的逻辑。

假设系统短信服务商存在以下两个服务商,我们需要做动态切换。 需要在接口上配置@EnvironmentProxySPI表示从环境变量配置点中获取当前使用的服务商。这里配置到属性 ${sms.impl}

java 复制代码
@EnvironmentProxySPI("${sms.impl}")
public interface SmsService {
}

// 给实现类定义别名
@BeanAliasName("某腾短信服务")
@Component
public class ASmsService implements SmsService {
}

@BeanAliasName("某移短信服务")
@Component
public class BSmsService implements SmsService {
}

2.1 配置当前使用的服务商

比如在配置文件中配置。 这里的值可以是@BeanAliasName的值,也可以是@Component的值,也可以具体的是全路径类名。

yaml 复制代码
sms:
  impl: 某移短信服务

2.3 @AutowiredProxySPI注入使用

java 复制代码
// 依赖注入
@AutowiredProxySPI
private SmsService smsService;

这样我们就完成了一个动态切换需求,只要我们改变配置配置属性${sms.impl}的值就会实时生效而无需重启服务,因为他注入的是一个代理对象每次执行时会先去实时获取当前使用的实现类然后才去执行调用, 并且在使用上与原先直接使用@Autowired基本毫无区别

2.4 定义不同的配置点

@EnvironmentProxySPI是用来配置环境变量相关的配置点,如果想要自定义配置比如在数据库中可实现自己的ProxySPI注解。

比如自定义DBProxySPI注解,并标记上@ProxySPI实现并指定具体配置获取逻辑实现类AnnotationProxyFactory即可。

然后DBProxySPI就可以像@EnvironmentProxySPI一样去使用了,下面是实现的伪代码

java 复制代码
@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) {
        // todo 根据注解从数据库获取要注入的实现类
        String configName = sysConfigDao.getConfig(spi.value());
        return springContext.getBean(configName);
    }
}


@DBProxySPI("${sms.impl}")
public interface SmsService {
}

其他

github项目地址

maven仓库地址

还在迭代中,第一个版本主要专注于动态切换, 还需要什么好玩的功能和特征请留下你的意见感谢。 觉得有用或者能学到点什么可以star下哈哈。

相关推荐
阿伟*rui4 分钟前
配置管理,雪崩问题分析,sentinel的使用
java·spring boot·sentinel
XiaoLeisj2 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
paopaokaka_luck2 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
dayouziei2 小时前
java的类加载机制的学习
java·学习
Yaml44 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~4 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616884 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
aloha_7895 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot
记录成长java5 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet
睡觉谁叫~~~5 小时前
一文解秘Rust如何与Java互操作
java·开发语言·后端·rust