zoukankan      html  css  js  c++  java
  • 使用 Spring 配置动态数据源实现读写分离

    关键词: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

  • 相关阅读:
    (4.25)Sqlserver中 登录用户只能看到自己拥有权限的库
    【查阅】mysql配置文件/参数文件重要参数笔录(my.cnf)
    【监控笔记】【2.5】DML(CDC)、DDL(DDL触发器)跟踪数据更改,数据库审计
    SQL Server 2008中的CDC(Change Data Capture)功能使用及释疑
    【监控笔记】【2.4】SQL Server中的 Ring Buffer 诊断各种系统资源压力情况
    【监控笔记】【2.3】扩展事件——慢查询SQL(执行超过3S的SQL)
    【监控笔记】【2.2】扩展事件——死锁监控
    最小配置启动SQL SERVER,更改SQL Server最大内存大小导致不能启动的解决方法
    【监控笔记】【2.1】扩展事件
    【扩展事件】跟踪超过3秒的SQL
  • 原文地址:https://www.cnblogs.com/commissar-Xia/p/11182169.html
Copyright © 2011-2022 走看看