Spring配置动态数据源实现读写分离的方法

发布时间 - 2026-01-10 22:38:30    点击率:

前言

最近因为工作的需要,要搭建的一个项目需要实现数据源的读写分离,在这里将代码进行分享,有需要的朋友们可以参考学习。

首先是配置数据源

<!--读数据源配置-->
<bean id="readDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init"destroy-method="close">
//配置省略
</bean>

<!--写数据源配置-->
<bean id="writeDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init"destroy-method="close">
//配置省略
</bean>

<!-- 动态数据源 -->
<bean id = "dataSource" class="com.potato.common.bean.DynamicDataSource" > 
 <!-- 已配置的数据源 --> 
 <property name="targetDataSources">  
 <map>   
  <entry key="READ" value-ref="readDataSource"/>   
  <entry key="WRITE" value-ref="writeDataSource"/>  
 </map> 
 </property> 
 <!-- 默认的数据源 --> 
 <property name="defaultTargetDataSource" ref="writeDataSource"/>
</bean>

数据源是如何切换的呢?通过动态数据源的配置我们知道原来是通过key来进行切换,这里要使用到org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource,我们可以编写自己的动态数据源类DynamicDataSource来继承它。

public class DynamicDataSource extends AbstractRoutingDataSource { 
 @Override 
 protected Object determineCurrentLookupKey() {  
  return DataSourceContextHolder.getType(); 
 }
}

还需要一个存放key的地方DataSourceContextHolder 为保证切换时线程安全我们使用ThreadLocal来保存我们的key。

public class DataSourceContextHolder {
 private static final Logger LOGGER = LoggerFactory.getLogger(DataSourceContextHolder.class);
 public static final String DATA_SOURCE_WRITE = "WRITE";
 public static final String DATA_SOURCE_READ = "READ";
 // 线程本地环境
 private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();

 // 设置数据源类型
 public static void setType(String type) {
  if(LOGGER.isDebugEnabled())
   LOGGER.debug("==============切换数据源,类型:"+type+"================");
  contextHolder.set(type);
 }
 // 获取数据源类型
 public static String getType() {
  return (contextHolder.get());
 }
 // 清除数据源类型
 public static void clearType() {
  contextHolder.remove();
 }
}

好了,我们可以通过操作DataSourceContextHolder来实现数据源动态的切换了。小伙伴们可能会说了,难道每次调用方法都要手动选择要切换的数据源类型?当然不是啦,Spring AOP登场。

@Component
@Aspect
public class DynamicDataSourceAspect {

 @Pointcut("execution (* com.potato.orm.mapper.*.select*(..)) || execution (* com.potato.orm.mapper.*.count*(..)) ")
 public void readMethodPointcut() {}

 @Pointcut("execution (* com.potato.orm.mapper.*.insert*(..)) || execution (* com.potato.orm.mapper.*.update*(..)) || execution (* com.potato.orm.mapper.*.delete*(..))")
 public void writeMethodPointcut() {}

 @Before("readMethodPointcut()")
 public void switchReadDataSource(){
  //System.out.println("============切换到读数据源===========");
  DataSourceContextHolder.setType(DataSourceContextHolder.DATA_SOURCE_READ);
 }

 @Before("writeMethodPointcut()")
 public void switchWriteDataSource(){
  //System.out.println("=============切换到写数据源==========");
  DataSourceContextHolder.setType(DataSourceContextHolder.DATA_SOURCE_WRITE);
 }

}

总结

好啦,以上就是这篇文章的全部内容了,在访问Mapper(本项目使用的是MyBatis啦,相当于是DAO)中查询方法时会切换到读数据源,增、删、改方法会切换到写数据源。希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。


# spring  # 读写分离  # 多数据源  # spring动态数据源  # 详解Nginx服务器中HTTP Headers相关的模块配置使用  # Spring动态数据源实现读写分离详解  # Mybatis注解实现多数据源读写分离详解  # resty更新header控制api版本数据源读写分离  # 切换到  # 我们可以  # 自己的  # 的是  # 在这里  # 好了  # 都要  # 说了  # 朋友们  # 还需要  # 这篇文章  # 来实现  # 好啦  # 要使  # 法会  # 小伙伴们  # 为保证  # 有疑问  # defaultTargetDataSource  # WRITE 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何快速辨别茅台真假?关键步骤解析  专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?  javascript中闭包概念与用法深入理解  laravel怎么通过契约(Contracts)编程_laravel契约(Contracts)编程方法  如何制作一个表白网站视频,关于勇敢表白的小标题?  三星、SK海力士获美批准:可向中国出口芯片制造设备  HTML透明颜色代码怎么让下拉菜单透明_下拉菜单透明背景指南【技巧】  如何在阿里云完成域名注册与建站?  如何实现建站之星域名转发设置?  Laravel如何设置定时任务(Cron Job)_Laravel调度器与任务计划配置  教你用AI将一段旋律扩展成一首完整的曲子  今日头条AI怎样推荐抢票工具_今日头条AI抢票工具推荐算法与筛选【技巧】  如何基于PHP生成高效IDC网络公司建站源码?  瓜子二手车官方网站在线入口 瓜子二手车网页版官网通道入口  WordPress 子目录安装中正确处理脚本路径的完整指南  Laravel N+1查询问题如何解决_Eloquent预加载(Eager Loading)优化数据库查询  Laravel如何升级到最新版本?(升级指南和步骤)  Python函数文档自动校验_规范解析【教程】  Laravel如何处理JSON字段的查询和更新_Laravel JSON列操作与查询技巧  矢量图网站制作软件,用千图网的一张矢量图做公司app首页,该网站并未说明版权等问题,这样做算不算侵权?应该如何解决?  如何注册花生壳免费域名并搭建个人网站?  Laravel如何发送系统通知?(Notification渠道示例)  如何用虚拟主机快速搭建网站?详细步骤解析  JavaScript如何实现继承_有哪些常用方法  免费网站制作appp,免费制作app哪个平台好?  如何在阿里云香港服务器快速搭建网站?  java ZXing生成二维码及条码实例分享  高防服务器租用指南:配置选择与快速部署攻略  Laravel Asset编译怎么配置_Laravel Vite前端构建工具使用  使用PHP下载CSS文件中的所有图片【几行代码即可实现】  Laravel如何配置和使用队列处理异步任务_Laravel队列驱动与任务分发实例  如何确保西部建站助手FTP传输的安全性?  laravel怎么配置和使用PHP-FPM来优化性能_laravel PHP-FPM配置与性能优化方法  如何快速配置高效服务器建站软件?  js实现点击每个li节点,都弹出其文本值及修改  Laravel如何使用Vite进行前端资源打包?(配置示例)  Windows10如何更改计算机工作组_Win10系统属性修改Workgroup  香港服务器如何优化才能显著提升网站加载速度?  Win11怎么修改DNS服务器 Win11设置DNS加速网络【指南】  Laravel Debugbar怎么安装_Laravel调试工具栏配置指南  Android中Textview和图片同行显示(文字超出用省略号,图片自动靠右边)  Win11任务栏卡死怎么办 Windows11任务栏无反应解决方法【教程】  nodejs redis 发布订阅机制封装实现方法及实例代码  Laravel中的withCount方法怎么高效统计关联模型数量  宙斯浏览器视频悬浮窗怎么开启 边看视频边操作其他应用教程  如何在万网自助建站平台快速创建网站?  Laravel怎么做缓存_Laravel Cache系统提升应用速度的策略与技巧  Laravel的HTTP客户端怎么用_Laravel HTTP Client发起API请求教程  Laravel Eloquent模型如何创建_Laravel ORM基础之Model创建与使用教程  Mybatis 中的insertOrUpdate操作