Spring 架构优雅的切换第三方平台接口
大约 1 分钟
设计思路
采用 代理委托模式。通过统一的接口,实现一个带有 @Primary 注解的上下文代理类(Context),由代理类根据配置项动态决定调用哪个具体实现。
代码实现结构
统一接口:使用或提取原接口,确保新旧平台拥有一致的行为。
public interface LearningPlatformService {
CourseInfo getCourseDetail(String courseId);
void pushLearningProgress(String userId, String progress);
}原实现类:保持原逻辑,指定 Bean 名称。
@Service("oldPlatformService")
public class OldPlatformServiceImpl implements LearningPlatformService { ... }新实现类:实现新接口逻辑,指定 Bean 名称。
@Service("newPlatformService")
public class NewPlatformServiceImpl implements LearningPlatformService { ... }核心代理类 (LearningPlatformContext)
利用 @Primary 让 Spring 优先注入此类。代理所有 LearningPlatformService 接口。
@Component
@Primary
public class LearningPlatformContext implements LearningPlatformService {
@Value("${learning.platform.type:old}") // 默认 old
private String platformType;
@Autowired
private Map<String, LearningPlatformService> platformMap;
private LearningPlatformService getService() {
String beanName = "new".equalsIgnoreCase(platformType)
? "newPlatformService" : "oldPlatformService";
return platformMap.get(beanName);
}
@Override
public CourseInfo getCourseDetail(String courseId) {
return getService().getCourseDetail(courseId);
}
@Override
public void pushLearningProgress(String userId, String progress) {
getService().pushLearningProgress(userId, progress);
}
}配置文件 (application.yml)
learning:
platform:
type: new # 可选值: old (旧平台), new (新平台)或配合数据字典,在 LearningPlatformContext 类中处理。
private IELearningService getService() {
QueryWrapper<SysDictItem> dictItemWrapper = new QueryWrapper<>();
dictItemWrapper.eq("item_value","trainSwitch");
SysDictItem sysDictItem = sysDictItemMapper.selectOne(dictItemWrapper);
if (null != sysDictItem && ResultConstants.DICT_ITEM_STATUS.equals(sysDictItem.getItemStatus())) {
return context.getBean("oldPlatformService", IELearningService.class);
} else {
return context.getBean("newPlatformService", IELearningService.class);
}
}