关键词:DataSource 、AbstractRoutingDataSource、AOP

首先是配置数据源

<!--读数据源配置-->
<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)中查询方法时会切换到读数据源,增、删、改方法会切换到写数据源。

------------------------------------------------

原文:https://www.cnblogs.com/Ti1077/p/9635692.html

使用 Spring 配置动态数据源实现读写分离的更多相关文章

  1. 使用Spring配置动态数据源实现读写分离

    最近搭建的一个项目需要实现数据源的读写分离,在这里将代码进行分享,以供参考.关键词:DataSource .AbstractRoutingDataSource.AOP 首先是配置数据源 <!-- ...

  2. 阿里P7教你如何使用 Spring 配置动态数据源实现读写分离

    最近搭建的一个项目需要实现数据源的读写分离,在这里将代码进行分享,以供参考. 关键词:DataSource .AbstractRoutingDataSource.AOP 首先是配置数据源 <!- ...

  3. mybatis用spring的动态数据源实现读写分离

    一.环境: 三个mysql数据库.一个master,两个slaver.master写数据,slaver读数据. 二.原理: 借助Spring的 AbstractRoutingDataSource 这个 ...

  4. spring 配置双数据源并读写分离

    摘自 开源项目Ibase4j    关键思想在于AbstractRoutingSource 类 还有方法名称和切入点去控制使用哪个数据源    1.首先在配置文件配置多个数据源 并且交给继承自spri ...

  5. Spring配置动态数据源-读写分离和多数据源

    在现在互联网系统中,随着用户量的增长,单数据源通常无法满足系统的负载要求.因此为了解决用户量增长带来的压力,在数据库层面会采用读写分离技术和数据库拆分等技术.读写分离就是就是一个Master数据库,多 ...

  6. 原理解密 → Spring AOP 实现动态数据源(读写分离),底层原理是什么

    开心一刻 女孩睡醒玩手机,收到男孩发来一条信息:我要去跟我喜欢的人表白了! 女孩的心猛的一痛,回了条信息:去吧,祝你好运! 男孩回了句:但是我没有勇气说不来,怕被打! 女孩:没事的,我相信你!此时女孩 ...

  7. Spring动态数据源实现读写分离

    一.创建基于ThreadLocal的动态数据源容器,保证数据源的线程安全性 package com.bounter.mybatis.extension; /** * 基于ThreadLocal实现的动 ...

  8. Spring Boot2(四):使用Spring Boot多数据源实现读写分离

    前言 实际业务场景中,不可能只有一个库,所以就有了分库分表,多数据源的出现.实现了读写分离,主库负责增改删,从库负责查询.这篇文章将实现Spring Boot如何实现多数据源,动态数据源切换,读写分离 ...

  9. Spring实现动态数据源,支持动态加入、删除和设置权重及读写分离

    当项目慢慢变大,訪问量也慢慢变大的时候.就难免的要使用多个数据源和设置读写分离了. 在开题之前先说明下,由于项目多是使用Spring,因此下面说到某些操作可能会依赖于Spring. 在我经历过的项目中 ...

随机推荐

  1. Mysql基础知识--触发器

    触发器的操作 在数据库系统中,当执行表事件时,则会激活触发器,从而执行其包含的操作 在具体的应用中,之所以会经常使用出发器数据对象,是由于该对象能够加强数据库表中数据的完整性约束和业务规则等. 一.创 ...

  2. VIJOS-P1232 核电站问题

    VIJOS-P1232 核电站问题 JDOJ 1373 https://neooj.com/oldoj/problem.php?id=1373 题目描述         一个核电站有N个放核物质的坑, ...

  3. Matlab c2d()函数的用法

    1.c2d()函数的用法 c2d()函数的作用是将s域的表达式转化成z域的表达式,s=0对应z=1. c2d()函数转化的方法有多种: ①zoh, 零阶保持器法,又称阶跃响应不变法: ②foh ,一阶 ...

  4. Autofac注册组件详解

    注册概念:我们通过创建 ContainerBuilder 来注册 组件 并且告诉容器哪些 组件 暴露了哪些 服务.组件 可以通过 反射 创建; 通过提供现成的 实例创建; 或者通过 lambda 表达 ...

  5. SWA2G422&485JK2G基础篇: STM32+W5500实现MQTT通信控制,485/422透传通信

    说明 这节实现的功能: STM32+W5500实现MQTT通信控制 细节功能: 1.DHCP动态获取IP 2.DNS域名解析 3.网口<--MQTT-->485/422透传通信 测试准备工 ...

  6. 【可视化】Vue基础

    作者 | Jeskson 来源 | 达达前端小酒馆 Vue简介 Vue框架,框架的作者,尤雨溪,组件化,快速开发的特点. 生命周期 beforeCreate:组件刚刚被创建 created:组件创建完 ...

  7. 消息队列:RabbitMQ安装

    1. 安装RabbitMQ之前需要先安装Erlang环境 然后配置环境变量 2. 安装完后 我们进入到我们安装到 sbin目录C:\Program Files\RabbitMQ Server\rabb ...

  8. Oracle--DBV命令行工具用法详解及坏块修复

    一,介绍 DBV(DBVERIFY)是Oracle提供的一个命令行工具,它可以对数据文件物理和逻辑两种一致性检查.但是这个工具不会检查索引记录和数据记录的匹配关系,这种检查必须使用analyze va ...

  9. Docker笔记:常用服务安装——Nginx、MySql、Redis(转载)

    转载地址:https://www.cnblogs.com/spec-dog/p/11320513.html 开发中经常需要安装一些常用的服务软件,如Nginx.MySql.Redis等,如果按照普通的 ...

  10. ASP.NET的MVC请求处理流程

    1.用户打开浏览器,在地址栏输入某个网址的URL并回车,浏览器便开始像该URL指定的服务器发起HTTP请求 .2.服务器的网站服务系统(IIS)接收到该请求,先检查自己是否认识该类请求,如果认识就直接 ...