首页 > 开发 > Java > 正文

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

2024-07-13 10:03:16
字体:
来源:转载
供稿:网友

前言

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

首先是配置数据源

<!--读数据源配置--><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@Aspectpublic 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)中查询方法时会切换到读数据源,增、删、改方法会切换到写数据源。希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。


注:相关教程知识阅读请移步到JAVA教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表