Spring AbstractRoutingDatasource实现多数据源指南
内容提要
本文介绍了如何使用Spring的AbstractRoutingDatasource来连接多个数据库并获取新的数据库连接。通过使用Context Holder来存储当前上下文,并使用AbstractRoutingDatasource查询上下文来确定实际的数据源。配置方面,可以使用pom.xml或application.properties文件来配置数据源。在使用AbstractRoutingDatasource时,需要设置上下文并在操作完成后清除上下文。通过这种方式,可以实现跨多个数据源和事务的数据访问逻辑。
延伸解读
上下文与线程绑定:多数据源路由的关键
文章强调Context Holder使用ThreadLocal存储上下文,使数据源选择与当前执行线程绑定。这在跨多个数据源和事务时尤为重要,因为不同线程可能同时处理不同客户端的请求。若未正确绑定,可能路由到错误的数据源。因此,在服务方法中设置上下文后,务必在操作完成后清除,避免线程复用导致上下文泄漏。
路由逻辑与数据访问代码解耦
通过扩展AbstractRoutingDataSource并重写determineCurrentLookupKey方法,数据源查找逻辑被封装在路由类中,业务代码无需关心具体使用哪个数据源。文章示例中,ClientService只需设置上下文,然后调用DAO,路由由框架透明处理。这种设计提高了代码的可维护性,也便于新增数据源。
配置方式:从XML到Spring Boot属性
文章展示了两种配置途径:传统方式在pom.xml中声明依赖,并通过Java配置类构建数据源映射;Spring Boot方式则利用application.properties定义每个数据源的属性,再通过@ConfigurationProperties绑定到POJO,最后构建DataSource Bean。后者更简洁,适合现代Spring Boot应用。
上下文清理:避免潜在的数据源污染
文章指出,使用AbstractRoutingDataSource时,必须在操作完成后清除上下文。示例中在服务方法内手动调用clear(),同时提到可以用AOP切点自动处理清除逻辑。若忘记清除,ThreadLocal中的上下文可能残留,导致后续请求使用错误的数据源。因此,清理步骤是保证路由正确性的必要环节。
Q&A
Spring AbstractRoutingDatasource 是什么,它有什么作用?
AbstractRoutingDatasource 是 Spring 提供的一个动态数据源路由组件,它根据当前上下文(Context)动态确定实际使用的 DataSource,从而将数据源查找逻辑从数据访问代码中解耦。
如何实现一个自定义的数据源路由器?
创建一个类继承 AbstractRoutingDataSource,并重写 determineCurrentLookupKey 方法,在该方法中返回当前上下文(例如从 ContextHolder 中获取的 ClientDatabase 枚举值)。
ContextHolder 为什么使用 ThreadLocal?
ContextHolder 使用 ThreadLocal 存储当前上下文,确保上下文与当前执行线程绑定。这样当数据访问逻辑跨越多个数据源并使用事务时,行为才可靠。
如何配置 AbstractRoutingDataSource 来映射多个数据源?
需要创建一个 Map<Object, Object> 作为 targetDataSources,将上下文(如 ClientDatabase 枚举)映射到对应的 DataSource 对象,然后通过 setTargetDataSources 设置到 AbstractRoutingDataSource 实例中,还可以通过 setDefaultTargetDataSource 指定默认数据源。
使用 AbstractRoutingDataSource 时,如何设置和清除上下文?
在服务层方法中,首先调用 ContextHolder 的 set 方法设置上下文,然后执行数据访问操作,操作完成后调用 clear 方法清除上下文。也可以使用 AOP 切点自动处理清除逻辑。
在 Spring Boot 中如何配置多个数据源的连接信息?
可以在 application.properties 文件中为每个数据源配置属性,例如 client-a.datasource.name 和 client-a.datasource.script,然后通过 @ConfigurationProperties 绑定到 POJO,再利用这些属性构建 DataSource Bean。