【参考】Spring(AbstractRoutingDataSource)实现动态数据源切换--转载

【参考】 利用Spring的AbstractRoutingDataSource解决多数据源的问题

一:关于具体的原理说明请卡上面的参考链接

二:操作步骤 :在你数据库配置文件中(我的是spring-dao.xml)配置多数据源  这里只展示了 数据库的配置

  1. <!-- 配置整合mybatis-->
  2. <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  3. <property name="locations">
  4. <list>
  5. <value>classpath*:jdbc.properties</value>
  6. </list>
  7. </property>
  8. </bean>
  9.  
  10. <!--配置数据库的连接池-->
  11. <bean id="abstractDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
  12. <!-- 配置链接属性 多数据源配置-->
  13. <!-- <property name="driverClass" value="${driver}"/>
  14. <property name="jdbcUrl" value="${url}"/>
  15. <property name="user" value="${username}"/>
  16. <property name="password" value="${password}"/>-->
  17. <!--配置c3p0连接池的私有属性-->
  18. <property name="maxPoolSize" value="30"/>
  19. <property name="minPoolSize" value="10"/>
  20. <!--关闭链接后不自动commit-->
  21. <property name="autoCommitOnClose" value="false"/>
  22. <property name="checkoutTimeout" value="1000"/>
  23. <!--获取连接失败重试次数-->
  24. <property name="acquireRetryAttempts" value="2"/>
  25. </bean>
  26. <!--多数据源配置 parent指向上面的配置数据库的连接池abstractDataSource 这里配置了两个数据源-->
  27. <bean id="base" parent="abstractDataSource">
  28. <property name="driverClass" value="${driver}"/>
  29. <property name="jdbcUrl" value="${url}"/>
  30. <property name="user" value="${username}"/>
  31. <property name="password" value="${password}"/>
  32. </bean>
  33. <bean id="server_1" parent="abstractDataSource">
  34. <property name="driverClass" value="${server_1_driver}"/>
  35. <property name="jdbcUrl" value="${server_1_url}"/>
  36. <property name="user" value="${server_1_username}"/>
  37. <property name="password" value="${server_1_password}"/>
  38. </bean>
  39.  
  40. <!-- 在RoutingDataSource类中读取 当前的返回值 并匹配key值 选择你的数据库源-->
  41. <bean id="dataSource" class="com.cdms.dao.resources.RoutingDataSource">
  42. <property name="targetDataSources">
  43. <map key-type="java.lang.String">
  44. <entry key="base" value-ref="base"></entry>
  45. <entry key="server_1" value-ref="server_1"></entry>
  46. </map>
  47. </property>
  48. <property name="defaultTargetDataSource" ref="base"></property>
  49. </bean>
  50.  
  51. <!-- 配置sqlSessionFactory对象-->
  52. <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  53. <!-- 注入数据库连接池-->
  54. <property name="dataSource" ref="dataSource"/>
  55. <!-- 配置Mybatisq全局文件:-->
  56. <property name="configLocation" value="classpath:mybatis-config.xml"/>
  57.  
  58. <!-- 扫描entity包-->
  59. <property name="typeAliasesPackage" value="com.cdms.entity"/>
  60. <!-- 扫描sql配置文件-->
  61. <property name="mapperLocations" value="classpath:mapper/*.xml"/>
  62. </bean>

另外 我的jdbc:perperties 配置文件是

  1. driver=com.mysql.jdbc.Driver
  2. url=jdbc:mysql://127.0.0.1:3306/course_design?useUnicode=true&characterEncoding=UTF-8
  3. username=root
  4. password=root
  5.  
  6. server_1_driver=com.mysql.jdbc.Driver
  7. server_1_url=jdbc:mysql://127.0.0.1:3306/course_design_test?useUnicode=true&characterEncoding=UTF-8
  8. server_1_username=root
  9. server_1_password=root
  1. RoutingDataSource类和DynamicDataSourceHolder
  1. public class RoutingDataSource extends AbstractRoutingDataSource{
  2. public final Logger logger = LoggerFactory.getLogger(this.getClass());
  3.  
  4. @Override
  5. protected Object determineCurrentLookupKey() {
  6. String dataSourceName = DynamicDataSourceHolder.getDataSourceName();
  7. if(dataSourceName == null){
  8. dataSourceName = DataSourceType.BASE.getDataSource();
  9. }
  10. logger.info("选择的数据库是:"+dataSourceName);
  11. return dataSourceName;
  12. }
  13. }
  1. public class DynamicDataSourceHolder {
  2.  
  3. //解决线程安全问题
  4. private static final ThreadLocal<String> holder = new ThreadLocal<String>();
  5.  
  6. public static void putDataSourceName(String dataName){
  7. holder.set(dataName);
  8. }
  9.  
  10. public static String getDataSourceName(){
  11. return holder.get();
  12. }
  13.  
  14. public static class DataSourceName{
  15. public final static String BASE = "base";
  16. }
  17. }

我们可以通过在holder中 put数据库的key值 来实现数据源的动态加载,其中 ThreadLocal<String> holder 保证了线程安全,而 RoutingDataSource
类里面的determineCurrentLookupKey()方法返回值 就是数据源的key值 配置文件通过这个key值找到了当前的配置源链接。这个是的测试 我就不多演示。

那我们怎么动态的进行数据链接呢,我们可以通过aop切面变成来实现

具体的aop切面编程的配置这里不多做介绍,可以参考之前的记过博文  有介绍
三:AOP注入实现 数据源的动态配置  首先需要第一一个切点。

  1. package com.cdms.aop;
  2.  
  3. import com.cdms.eunms.DataSourceType;
  4.  
  5. import java.lang.annotation.*;
  6.  
  7. /**
  8. * 创建 by 草帽boy on 2017/3/29.
  9. */
  10. @Target({ElementType.PARAMETER, ElementType.METHOD})
  11. @Retention(RetentionPolicy.RUNTIME)
  12. @Documented
  13. public @interface ChooseDataSource {
  14. /**
  15. * 数据库名称 默认似base
  16. * @return 数据库名称
  17. */
  18. String dataSourceName() default "base";
  19.  
  20. }

然后定义一个切面方法

  1. package com.cdms.aop;
  2.  
  3. import com.cdms.dao.resources.DynamicDataSourceHolder;
  4. import com.cdms.eunms.DataSourceType;
  5. import org.aspectj.lang.ProceedingJoinPoint;
  6. import org.aspectj.lang.annotation.*;
  7. import org.springframework.stereotype.Component;
  8.  
  9. import java.lang.reflect.Method;
  10.  
  11. /**
  12. * 创建 by 草帽boy on 2017/3/29.
  13. */
  14. @Aspect
  15. @Component
  16. public class GetDataSource {
  17.  
  18. /**
  19. * 切面设置要选择的数据库
  20. * @param joinPoint
  21. * @return
  22. * @throws Throwable
  23. */
  24. @Around("@annotation(com.cdms.aop.ChooseDataSource)")
  25. public Object permission(ProceedingJoinPoint joinPoint) throws Throwable {
  26. Object target = joinPoint.getTarget();
  27. Object[] args = joinPoint.getArgs();
  28. Method method = getMethod(joinPoint, args);
  29. //获取数据库名称参数
  30. ChooseDataSource chooseDataSource = method.getAnnotation(ChooseDataSource.class);
  31. if(chooseDataSource != null){
  32. String dataSourceName = chooseDataSource.dataSourceName();
  33. //坚持名称是否合法 如果不合法 就用默认数据库
  34. if(DataSourceType.check(dataSourceName)){
  35. DynamicDataSourceHolder.putDataSourceName(dataSourceName);
  36. }else {
  37. DynamicDataSourceHolder.putDataSourceName(DataSourceType.BASE.getDataSource());
  38. }
  39. }
  40. return joinPoint.proceed();
  41. }
  42.  
  43. /**
  44. * 获取切面方法
  45. * @param joinPoint
  46. * @param args
  47. * @return
  48. * @throws NoSuchMethodException
  49. */
  50. private Method getMethod(ProceedingJoinPoint joinPoint, Object[] args) throws NoSuchMethodException {
  51. // Class[] argsClazz = new Class[args.length];
  52. // for(int i = 0 ; i < args.length; i++){
  53. // argsClazz[i] = args[i].getClass();
  54. // }
  55. String methodName = joinPoint.getSignature().getName();
  56. Class clazz = joinPoint.getTarget().getClass();
  57. Method[] methods = clazz.getMethods();
  58. for(Method method : methods) {
  59. if (methodName.equals(method.getName())) {
  60. return method;
  61. }
  62. }
  63. return null;
  64. }
  65. }
  1. <!-- 启动@aspectj的自动代理支持-->
  2. <aop:aspectj-autoproxy expose-proxy="true"></aop:aspectj-autoproxy>
  3. <!-- 定义aspect类 -->
  4. <bean id="logAopAction" class="com.cdms.aop.LogAopAction"></bean>
  5. <bean id="aopTest" class="com.cdms.aop.DemoAopTest"></bean>
  6. <bean id="getDataSourcesName" class="com.cdms.aop.GetDataSource"></bean>

在之后需要改变数据源的地方 只需要 @ChooseDataSource(dataSourceName = "server_1")   表明你的数据源就看了

使用单元测试的结果是 ;(@ChooseDataSource(dataSourceName = "server_1") )

(@ChooseDataSource(dataSourceName = "base") )

这个是注入点:

Spring 实现动态数据源切换--转载 (AbstractRoutingDataSource)的使用的更多相关文章

  1. Spring(AbstractRoutingDataSource)实现动态数据源切换--转载

    原始出处:http://linhongyu.blog.51cto.com/6373370/1615895 一.前言 近期一项目A需实现数据同步到另一项目B数据库中,在不改变B项目的情况下,只好选择项目 ...

  2. SpringMVC 利用AbstractRoutingDataSource实现动态数据源切换

    SpringMVC 利用AbstractRoutingDataSource实现动态数据源切换 本文转载至:http://exceptioneye.iteye.com/blog/1698064 Spri ...

  3. AbstractRoutingDataSource动态数据源切换,AOP实现动态数据源切换

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/u012881904/article/de ...

  4. 30个类手写Spring核心原理之动态数据源切换(8)

    本文节选自<Spring 5核心原理> 阅读本文之前,请先阅读以下内容: 30个类手写Spring核心原理之自定义ORM(上)(6) 30个类手写Spring核心原理之自定义ORM(下)( ...

  5. Spring主从数据库的配置和动态数据源切换原理

    原文:https://www.liaoxuefeng.com/article/00151054582348974482c20f7d8431ead5bc32b30354705000 在大型应用程序中,配 ...

  6. 【开发笔记】- AbstractRoutingDataSource动态数据源切换,AOP实现动态数据源切换

    AbstractRoutingDataSource动态数据源切换 上周末,室友通宵达旦的敲代码处理他的多数据源的问题,搞的非常的紧张,也和我聊了聊天,大概的了解了他的业务的需求.一般的情况下我们都是使 ...

  7. Spring动态切换多数据源事务开启后,动态数据源切换失效解决方案

    关于某操作中开启事务后,动态切换数据源机制失效的问题,暂时想到一个取巧的方法,在Spring声明式事务配置中,可对不改变数据库数据的方法采用不支持事务的配置,如下: 对单纯查询数据的操作设置为不支持事 ...

  8. AbstractRoutingDataSource 实现动态数据源切换原理简单分析

    AbstractRoutingDataSource 实现动态数据源切换原理简单分析 写在前面,项目中用到了动态数据源切换,记录一下其运行机制. 代码展示 下面列出一些关键代码,后续分析会用到 数据配置 ...

  9. Java注解--实现动态数据源切换

    当一个项目中有多个数据源(也可以是主从库)的时候,我们可以利用注解在mapper接口上标注数据源,从而来实现多个数据源在运行时的动态切换. 实现原理 在Spring 2.0.1中引入了Abstract ...

随机推荐

  1. HTTP概念解析

    HTTP--Hyper Text Transfer Protocol HTTP详细介绍(火星的小白 51CTO): https://blog.51cto.com/13570193/2108347 先进 ...

  2. HTML5 新增的 input 事件

    以往 HTML 的 input 輸入框,無法即時反映使用者的輸入內容.onkeyup.onkeydown 事件,無法即時.精確地取得使用者的輸入資料:而 onchange.onblur 事件,要等到失 ...

  3. 解决SVN Cleanup错误: Failed to run the WC DB work queue associated with

    [内容来源自https://www.cnblogs.com/ANCAN-RAY/p/8961832.html] 在svn本地目录更新文件夹时,更新失败. 然后svn提示我,让我cleanup一下,于是 ...

  4. javafx:JavaFX Scene Builder 2.0打开含有第三方jar包的fxml文件报错 Caused by: java.lang.ClassNotFoundException

    报错如下: java.io.IOException: javafx.fxml.LoadException: /C:/User.................test.fxml at com.orac ...

  5. 我的Scala之路(1):列表List操作

    List() 或 Nil 空 List List("Cool", "tools", "rule) 创建带有三个值"Cool",&q ...

  6. python day05

    数字类型 1.整型:整数 num = 1000000000000 type(num) --->int 2.浮点型:小数 num = 123.2341 type(num) --->float ...

  7. 关于 insufficient memory case 4 的解决记录

    用户在上传图片的时候,系统会报异常 insufficient memory case 4,追踪代码发生在jdk中 image.io 的 read() 方法.这是一个耽搁了很久的bug,客户反馈了好几次 ...

  8. API简介

    概述 API(Application Programming Interface),应用程序编程接口.Java API是一本程序员的 字典 ,是JDK中提供给我们使用的类的说明文档.这些类将底层的代码 ...

  9. modelsim10.1a安装破解说明

    安装包网盘下载链接:https://pan.baidu.com/s/1X9kUUXMCoikyjCQ_HKdD5g 提取码:3lfd 1.下载文件解压找到"modelsim-win32-10 ...

  10. springboot配置SSL自签名证书

    1.证书生成 每一个JDK或者JRE里都有一个工具,叫做:keytool,安装了jdk或jre之后,配置好JAVA环境之后,就可以直接在控制台使用该命令生成自签名证书: 在控制台输入: keytool ...