核心思路是利用Spring Boot的profile机制结合AbstractRoutingDataSource,在启动时读取环境变量(如spring.profiles.active),通过ApplicationContext动态注册数据源,并在运行时基于ThreadLocal与AOP实现方法级数据源路由,无需改代码、不重启即可完成环境切换。
核心思路是让 spring boot 启动时读取环境变量(如 spring.profiles.active),结合 applicationcontext 和 abstractroutingdatasource,在容器初始化阶段或运行时动态注册/路由到对应数据源,无需改代码、不重启服务即可完成环境切换。
这是最轻量、最标准的起点。Spring Boot 会自动加载 application-{profile}.yml 文件,并根据激活的 profile 决定使用哪套配置。
spring: profiles: active: @spring.profiles.active@(Maven 构建时注入)或直接设为 dev
application-dev.yml → H2 内存库application-test.yml → 测试 MySQL 实例application-prod.yml → 生产集群地址+连接池参数java -jar app.jar --spring.profiles.active=prodexport SPRING_PROFILES_ACTIVE=prod
适用于需要在容器启动后、Bean 创建前就完成数据源绑定的场景(比如某些依赖 DataSource 的组件必须早于数据源初始化)。
ApplicationContextAware 和 EnvironmentAware,拿到容器和当前 profile@PostConstruct 或自定义初始化方法中,调用 applicationContext.getBeanFactory().registerSingleton() 注册对应数据源实例@Primary 或 SqlSessionFactory 引用的名称一致,否则注入失败这是最灵活、最常用的动态切换方式,支持方法级、事务级甚至请求级的数据源选择。
AbstractRoutingDataSource,重写 determineCurrentLookupKey()
ThreadLocal<String> 存储当前线程要使用的数据源标识(如 "master"、"slave"、"history")@DS("test"))在方法执行前设置 ThreadLocal 值,执行后清理生产部署时,环境变量通常由运维侧注入,应用只需“读取并响应”。
docker run -e SPRING_PROFILES_ACTIVE=prod -e DB_URL=jdbc:mysql://db-prod:3306/mydb ...
application-prod.yml 内容以键值对形式存入 ConfigMap,挂载为 volume 或 envFromSPRING_PROFILES_ACTIVE 和 spring.profiles.active 读取 profile,其他变量需在配置中显式引用,例如:spring.datasource.url=${DB_URL:jdbc:h2:mem:test}