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

  • 相关阅读:
    zoj 1239 Hanoi Tower Troubles Again!
    zoj 1221 Risk
    uva 10192 Vacation
    uva 10066 The Twin Towers
    uva 531 Compromise
    uva 103 Stacking Boxes
    稳定婚姻模型
    Ants UVA
    Golden Tiger Claw UVA
    关于upper、lower bound 的探讨
  • 原文地址:https://www.cnblogs.com/commissar-Xia/p/11182169.html
Copyright © 2011-2022 走看看