基于AbstractRoutingDataSource实现动态切换数据源

/**
 * DataSource
注解接口
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface
DataSourceAnnotation {
    String value() default DataSourceSelect.MASTER;
}

/**
 *
注解前后增强获取数据库清空数据库
 */
@Aspect
@Component
@Logger
public class DatasourceAspect {
@Pointcut("@annotation(com.example.demo.config.DataSourceAnnotation)")
public void pointcut() {
}
    @Before("pointcut()")
    public void beforeExecute(JoinPoint
joinPoint) {
        Method method =
((MethodSignature) joinPoint.getSignature()).getMethod();
        DataSourceAnnotation annotation = method.getAnnotation(DataSourceAnnotation.class);
        if (annotation == null) {
            annotation =
joinPoint.getTarget().getClass().getAnnotation(DataSourceAnnotation.class);
             DynamicDataSource.setDataSource(DataSourceSelect.MASTER);
        }else{
            // 切换数据源
            DynamicDataSource.setDataSource (annotation.value());
        }
    }
    @After("pointcut()")
    public void afterExecute() {
        DynamicDataSource.clear();
    }
}

定义数据源类来存储多个数据源选择

public interface DataSourceSelect {
    /**
     *
主库源
     */
   
String MASTER="master";
    /**
     *
从库源
     */
   
String  SLAVE ="slave";

}

继承AbstractRoutingDataSource重写方法实现把默认数据源和目标数据源注入

并提供ThreadLocal线程保证数据源隔离。

public class DynamicDataSource extends AbstractRoutingDataSource
{
    private final Logger logger = LoggerFactory.getLogger(DynamicDataSource.class);
    private static final ThreadLocal<String> DATA_SOURCE_CONTEXT_HOLDER = new ThreadLocal<>();

public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
    }
    @Override
    protected Object
determineCurrentLookupKey() {
        return getDataSource();
    }
     static void setDataSource(String
dataSource) {
        DATA_SOURCE_CONTEXT_HOLDER.set(dataSource);
    }

public static String getDataSource() {
        return DATA_SOURCE_CONTEXT_HOLDER.get();
    }

static void clear() {
        DATA_SOURCE_CONTEXT_HOLDER.remove();
    }

}

把数据源配置路径与数据源匹配,并利用子类调用有参构造调用父类AbstractRoutingDataSource的方法把数据源信息加载进datasource

/**
 *
配置多数据源
 * @author xiaohe
 * @version V1.0.0
 */
@Configuration
public class DynamicDataSourceConfig {

@Bean
    @ConfigurationProperties("spring.datasource.master")
    public DataSource
masterDataSource(){

return DruidDataSourceBuilder.create().build();
    }

@Bean
    @ConfigurationProperties("spring.datasource.slave")
    public DataSource
slaveDataSource(){

return DruidDataSourceBuilder.create().build();
    }
    @Bean
    @Primary
    public DynamicDataSource
dataSource(DataSource masterDataSource, DataSource
slaveDataSource) {
        Map<Object, Object> targetDataSources = new HashMap<>(5);
        targetDataSources.put(DataSourceSelect.MASTER, masterDataSource);
        targetDataSources.put(DataSourceSelect.SLAVE, slaveDataSource);
        return new DynamicDataSource(masterDataSource, targetDataSources);
    }

}

Application启动项,exclude = DataSourceAutoConfiguration.class排除自动注入数据源的配置,加上Import 用来加加载我们定义的datasource。

 
@ComponentScan(basePackages ="com.example.demo.*")
@EnableJpaRepositories("com.example.demo.repository")
@Import(DynamicDataSourceConfig.class)
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class DruidApplication {
    public static void main(String[] args) {
        SpringApplication.run(DruidApplication.class, args);
    }
}

FQA:

9. 注解没有被注入到ioc容器导致注解失效。

10. 多数据源的动态切换,在程序运行时,把数据源数据源动态织入到程序中,灵活的进行数据源切换。
- 基于多数据源的动态切换,我们可以实现读写分离,这么做缺点也很明显,无法动态的增加数据源。

只支持单库事务,也就是说切换数据源要在开启事务之前执行。

spring DataSourceTransactionManager进行事务管理,开启事务,会将数据源缓存到DataSourceTransactionObject对象中进行后续的commit rollback等事务操作。

基于AbstractRoutingDataSource实现动态切换数据源的更多相关文章

  1. AbstractRoutingDataSource 实现动态切换数据源

    扩展AbstractRoutingDataSource类 package com.datasource.test.util.database; import org.springframework.j ...

  2. Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法

    一.开篇 这里整合分别采用了Hibernate和MyBatis两大持久层框架,Hibernate主要完成增删改功能和一些单一的对象查询功能,MyBatis主要负责查询功能.所以在出来数据库方言的时候基 ...

  3. hibernate动态切换数据源

    起因: 公司的当前产品,主要是两个项目集成的,一个是java项目,还有一个是php项目,两个项目用的是不同的数据源,但都是mysql数据库,因为java这边的开发工作已经基本完成了,而php那边任务还 ...

  4. 在使用 Spring Boot 和 MyBatis 动态切换数据源时遇到的问题以及解决方法

    相关项目地址:https://github.com/helloworlde/SpringBoot-DynamicDataSource 1. org.apache.ibatis.binding.Bind ...

  5. Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源方法

    一.开篇 这里整合分别采用了Hibernate和MyBatis两大持久层框架,Hibernate主要完成增删改功能和一些单一的对象查询功能,MyBatis主要负责查询功能.所以在出来数据库方言的时候基 ...

  6. Spring学习总结(16)——Spring AOP实现执行数据库操作前根据业务来动态切换数据源

    深刻讨论为什么要读写分离? 为了服务器承载更多的用户?提升了网站的响应速度?分摊数据库服务器的压力?就是为了双机热备又不想浪费备份服务器?上面这些回答,我认为都不是错误的,但也都不是完全正确的.「读写 ...

  7. Spring+Mybatis动态切换数据源

    功能需求是公司要做一个大的运营平台: 1.运营平台有自身的数据库,维护用户.角色.菜单.部分以及权限等基本功能. 2.运营平台还需要提供其他不同服务(服务A,服务B)的后台运营,服务A.服务B的数据库 ...

  8. Spring动态切换数据源及事务

    前段时间花了几天来解决公司框架ssm上事务问题.如果不动态切换数据源话,直接使用spring的事务配置,是完全没有问题的.由于框架用于各个项目的快速搭建,少去配置各个数据源配置xml文件等.采用了动态 ...

  9. AOP获取方法注解实现动态切换数据源

    AOP获取方法注解实现动态切换数据源(以下方式尚未经过测试,仅提供思路) ------ 自定义一个用于切换数据源的注解: package com.xxx.annotation; import org. ...

随机推荐

  1. IDEA构建支持cdh版本和scala的maven项目注意事项

    工具和环境 idea2018.1 , scala2.11.8, scala的idea支持包,下载地址 maven3.3.9 win10系统 1.maven环境配置 下载解压maven包,(也可以使用i ...

  2. python 最小二乘 leastsq 函数实现 法线式 解决与x轴垂直问题

    当使用y=kx+b时,与x轴垂直的直线无法计算.因此使用法线式ysin(theta)+xcos(theta) = dist.貌似这么用有点复杂了,直接使用ax+by=1不知道能不能计算,未测试. # ...

  3. Ubuntu 14.04 改变文件或者文件夹的拥有者

    只有系统管理者(root)才有这样的权限#将文件 file1.txt 的拥有者设为 runoob,群体的使用者 runoobgroupchown runoob:runoobgroup file1.tx ...

  4. Jedis API操作redis数据库

    1.配置文件 classpath路径下,新建redis.properties配置文件 配置文件内容 # Redis settings redis.host=127.0.0.1 redis.port=6 ...

  5. Java基础系列 - 数组、二维数组、对象数组

    package com.test2; public class demo2 { public static void main(String[] args) { /** * 一维数组使用 */ //数 ...

  6. ssh sshpass随笔

    1: 当通过ssh连接远程服务器的时候,可能会出现以下繁琐场景,需要手工输入yes: ssh username@ip 这对于某些分布式集群来说是不行的,甚至导致集群都不能启动成功,对于像pssh,ps ...

  7. [TJOI2019]甲苯先生和大中锋的字符串——后缀自动机+差分

    题目链接: [TJOI2019]甲苯先生和大中锋的字符串 对原串建后缀自动机并维护$parent$树上每个点的子树大小,显然子树大小为$k$的节点所代表的子串出现过$k$次,那么我们需要将$[len[ ...

  8. Centos7 node npm升级版本

    安装npm 官网:https://nodejs.org/en/download/ 下载LTS Linux Binaries (x64)版本. # tar xf node-v10.16.3-linux- ...

  9. PowerDesigner 使用小结

    这里总结一篇关于数据建模工具 PowerDesigner 的使用小技巧,下面列出的两个应用场景要在网上现找解决方案的话还真不一定好找,所以选择将这两个棘手的问题先记下来. 1. PDM 中表间关系出现 ...

  10. Eclipse自动生成作者、日期注释等功能设置 (转载)

    原文地址:http://blog.sina.com.cn/s/blog_4080505a0101guoh.html 在使用Eclipse 编写Java代码时,自动生成的注释信息都是按照预先设置好的格式 ...