基于AbstractRoutingDataSource实现动态切换数据源
基于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实现动态切换数据源的更多相关文章
- AbstractRoutingDataSource 实现动态切换数据源
扩展AbstractRoutingDataSource类 package com.datasource.test.util.database; import org.springframework.j ...
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
一.开篇 这里整合分别采用了Hibernate和MyBatis两大持久层框架,Hibernate主要完成增删改功能和一些单一的对象查询功能,MyBatis主要负责查询功能.所以在出来数据库方言的时候基 ...
- hibernate动态切换数据源
起因: 公司的当前产品,主要是两个项目集成的,一个是java项目,还有一个是php项目,两个项目用的是不同的数据源,但都是mysql数据库,因为java这边的开发工作已经基本完成了,而php那边任务还 ...
- 在使用 Spring Boot 和 MyBatis 动态切换数据源时遇到的问题以及解决方法
相关项目地址:https://github.com/helloworlde/SpringBoot-DynamicDataSource 1. org.apache.ibatis.binding.Bind ...
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源方法
一.开篇 这里整合分别采用了Hibernate和MyBatis两大持久层框架,Hibernate主要完成增删改功能和一些单一的对象查询功能,MyBatis主要负责查询功能.所以在出来数据库方言的时候基 ...
- Spring学习总结(16)——Spring AOP实现执行数据库操作前根据业务来动态切换数据源
深刻讨论为什么要读写分离? 为了服务器承载更多的用户?提升了网站的响应速度?分摊数据库服务器的压力?就是为了双机热备又不想浪费备份服务器?上面这些回答,我认为都不是错误的,但也都不是完全正确的.「读写 ...
- Spring+Mybatis动态切换数据源
功能需求是公司要做一个大的运营平台: 1.运营平台有自身的数据库,维护用户.角色.菜单.部分以及权限等基本功能. 2.运营平台还需要提供其他不同服务(服务A,服务B)的后台运营,服务A.服务B的数据库 ...
- Spring动态切换数据源及事务
前段时间花了几天来解决公司框架ssm上事务问题.如果不动态切换数据源话,直接使用spring的事务配置,是完全没有问题的.由于框架用于各个项目的快速搭建,少去配置各个数据源配置xml文件等.采用了动态 ...
- AOP获取方法注解实现动态切换数据源
AOP获取方法注解实现动态切换数据源(以下方式尚未经过测试,仅提供思路) ------ 自定义一个用于切换数据源的注解: package com.xxx.annotation; import org. ...
随机推荐
- 开启php的PDO扩展,mysql扩展
打开php.ini配置文件,找到extension=php_pdo.dll 和 extension=php_pdo_mysql.dll ,去掉前面“;”的注释,修改后的两行配置内容如下: extens ...
- javascript中的contains方法和compareDocumentPosition方法
IE有许多好用的方法,后来都被其他浏览器抄袭了,比如这个contains方法.如果A元素包含B元素,则返回true,否则false.唯一不支持这个方法的是IE的死对头firefox.不过火狐支持com ...
- ES--Kibana相关操作创建索引和Mapping
创建索引 kibana 使用如下命令进行创建索引内容. PUT test_index/ 创建别名 POST _aliases { "actions": [{ "add&q ...
- JS-数组与伪数组
数组与伪数组 把符合以下条件的对象称为伪数组: 具有length属性 按索引方式存储数据 不具有数组的push,pop等方法 伪数组(类数组):无法直接调用数组方法或期望length属性有什么特殊的行 ...
- 42 Flutter仿京东商城项目 修改默认收货地址 显示默认收货地址
CheckOut.dart import 'package:flutter/material.dart'; import '../services/ScreenAdapter.dart'; impor ...
- ubuntu server 18.04 单机安装openstack
https://ubuntu.com/openstack/install#workstation-deployment sudo snap install microstack --classic - ...
- STL函数适配器
一:适配器简介 C++中有三类适配器,分别是容器适配器,迭代器适配器和函数适配器,这里主要介绍函数适配器. (一)函数适配器简介 STL中已经定义了大量的函数对象,但是有时候需要对函数返回值进行进一步 ...
- Java环境中,word文档转PDF直接打开浏览而非下载
在平台上,需要把文档直接浏览而非下载,实现方法是先把文档转为PDF文件, 但在linux系统中确实汉字字库,所以转换失败,以下是解决方法 后面正式服务器也要添加字库,不然会转换出乱码文件,处理步骤如下 ...
- (四)UML之顺序图(时序图)
一.概念 顺序图是交互图的一种形式,它显示对象沿生命线发展,对象之间随时间的交互表示为从源生命线指向目标生命线的消息.顺序图能很好地显示那些对象与其它那些对象通信,什么消息触发了这些通信,顺序图不能很 ...
- 文件被sourceTree忽略了怎么办