Multiple Versions Coexist —— 一种区别于传统方案的运行时多版本管理机制的功能介绍

30 阅读5分钟

注:由于作者口才不佳,所以此文章由AI辅助生成,具体功能效果和解释以源码为主

视频讲解:(暂未完成)

✍ 作者说明

免责声明 作者是一位在“获取信息能力在原始时代与现代文明之间反复横跳”的开发者。如果本组件的设计与市面上某些方案不慎撞车,那纯属思路巧合,并非抄袭。若你发现类似实现,也欢迎交流一起完善生态。

还有由于哥们的源码注释写的过于详细,这里就大致描述主要功能注解的作用,具体的细节方面请阅读maven源码,接下来哥们给你康康我的注释,没错它甚至是双语的:

2F]LH8~]6KL%RK3FDL}8M.png

前言:关于 Spring Boot 路径匹配的兼容性

自 Spring Boot 2.6 起切换为 PathPatternParser,路径匹配逻辑发生了重大变化,旧的 AntPathMatcherPatternsRequestCondition 在新版本中无法完全兼容。

为确保组件在不同 Spring Boot 版本中的一致表现,Multiple Versions Coexist 提供了双方案支持:

  • Ant 风格路径匹配(适配 2.5 及以下版本)
  • PathPatternParser 匹配机制(适配 2.6+)

组件会自动探测当前可用机制,优先使用 PathPatternParser,不可用则自动回退。

因此:使用本组件无需关心 Spring Boot 的版本差异,可开箱即用。


关于文章阅读顺序

本文旨在介绍组件的各类注解、扩展能力与配置方式。 若你需要查看完整示例项目或更先进的用法,请阅读源码。

1. @CoexistenceVersion —— 声明接口所属版本

用于指定:

  • 某个类下所有方法属于某版本
  • 某个方法单独属于某版本
  • 类与方法同时标注时,以方法优先

支持同时在不同类或方法标注相同版本,以实现灵活的版本结构划分。

注:如果在实际操作中同时存在多个版本,建议通过multi.version.properties的配置来达到最后生效的只有一个版本的效果

注:如果在实际操作中需要同时存在多个版本并行的情况,请重写DualRequestMappingHandlerMapping中的PathPatternParserMatch方法(适配 2.6+)或者AntStylePatternsMatch方法(适配 2.5 及以下版本),且定制自己的判断条件来决定此时访问者走哪个版本的接口

使用示例

@RestController
@RequestMapping("/demo")
@CoexistenceVersion(version = "1.0.0")
public class DemoController {
​
    @GetMapping("/v1")
    public void v1() {
        System.out.println("run!");
    }
​
    @CoexistenceVersion(version = "2.0.0")
    @GetMapping("/v2")
    public void v2() {
        System.out.println("run!");
    }
}

效果:

  • /demo/v1 → v1.0.0
  • /demo/v2 → v2.0.0

2. @InterfacePriority —— 路径相同接口的优先级选择

用于处理“相同路径、不同版本或不同实现”时的优先级,比对规则:

  • 数字越大 → 优先级越高(默认 0)
  • 可通过继承 MulRegisterHandlerMethod 覆盖排序规则

示例

@RestController
@RequestMapping("/demo")
public class Demo {
​
    @InterfacePriority(2)
    @GetMapping("/same")
    public void high() {}
​
    @InterfacePriority(1)
    @GetMapping("/same")
    public void low() {}
}

默认行为:仅注册优先级更高的 high()。


3. @NotIncCoexistenceVersion —— 排除版本控制

当你不希望某方法受到类级 @CoexistenceVersion 影响,可使用此注解。

示例

@RestController
@RequestMapping("/demo")
@CoexistenceVersion("1.0.0")
public class Demo {
​
    @GetMapping("/v1")
    public void v1() {}
​
    @NotIncCoexistenceVersion
    @GetMapping("/public")
    public void publicApi() {}
}

结果: /public 作为普通接口注册,不归属到 1.0.0。


4. @SynchronousOperation,@SynchronousOperations —— 傻瓜式 AOP 同步操作

这是本组件的附加“亮点功能”:不依赖 AOP 也能实现简单的“方法前/后操作”。

配置方式:

  • 类上标注 → 作用于类内全部方法
  • 方法上标注 → 仅作用于单个方法
  • 方法标注优先级大于类标注

此注解必须配合继承 SynOpeImplementation 的类使用。

示例

@RestController
@RequestMapping("/demo")
public class Demo {
​
    @SynchronousOperation("afterCall")
    @GetMapping("/run")
    public void run() {}
}
或
@RestController
@RequestMapping("/demo")
public class Demo {
​
    @SynchronousOperations(
        @SynchronousOperation("afterCall"),
        @SynchronousOperation("afterCall2")
    )
    @GetMapping("/run")
    public void run() {}
}
​
public class DemoAfter extends SynOpeImplementation {
    public void afterCall(Object[] args, Object result, Throwable throwable) {
        System.out.println("after logic");
    }
    public void afterCall2(Object[] args, Object result, Throwable throwable) {
        System.out.println("after logic");
    }
}

5. @UnSynchronousOperation —— 禁用同步操作

用于在类开启同步操作情况下排除某个方法。


6. @AfterOperation & @BeforeOperation —— 前后置执行逻辑

只需在 SynOpeImplementation 中标注:

public class Demo extends SynOpeImplementation {
​
    @BeforeOperation
    public String before() {
        return "before";
    }
}

与 @SynchronousOperation 配合后:

  • @BeforeOperation → 在原方法之前执行
  • @AfterOperation → 在原方法之后执行(默认)

🔧 可扩展的内部方法(高级用法)

⚠ 湿区警告:若不熟悉 Spring 内部原理,请不要轻易改动。

1. DualControllerMappingConfig

用于启动当前组件的注册流程。

2. SynOpeImplementation

用于实现你的“同步操作”逻辑。

3. DualRequestMappingHandlerMapping

核心组件,负责:

  • CoexistenceVersion 的动态注册
  • InterfacePriority 的优先级注入
  • 路径分析兼容处理

4. getMethodPath

用于确定方法路径(兼容 Spring Boot 多版本)。

5. unregisterPath

动态注销接口(开发 Beta 项目时尤其好用)。

6. watchConfigFile

用于监听“本地文件控制版本开放”的实时更新。

7.PathPatternParserMatch

判断访问者路径lookupPath是否匹配当前路径pattern

8.AntStylePatternsMatch

判断访问者路径lookupPath是否匹配当前路径pattern


⚙️ Properties 配置说明

1. multi.version.properties

控制多版本注册:

参数作用
start是否开启多版本管理
Include仅注册的版本
UnInclude排除的版本
MaxNum最大注册版本数
SortingMethod版本排序方式

2. multi.version.file

用于实时控制版本开放(无需重启项目):

参数说明
FileConfiguration是否启用本地文件版本控制
FilePath文件路径(必须到文件名)
FileRefreshTime刷新周期(毫秒)

3. multi.version.info

用于在项目运行时收集展示版本元数据。


🎯 结语

Multiple Versions Coexist 并非传统意义的“API Versioning 工具”, 它是一种更加灵活的 运行时接口多版本共存机制, 同时附带更轻量的 同步操作(类AOP)能力,适合:

  • 多版本并行维护
  • Beta / AB Test
  • 付费版与免费版差异控制
  • 接口行为动态替换
  • 无侵入式版本灰度切换