基于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. ...
随机推荐
- jmeter+ant执行 报错:Reference xslt.classpath not found 【采坑记录】
问题: report: BUILD FAILED E:\jmeter\apache-jmeter-4.0\testcase\build.xml:29: The following error occu ...
- 前端武器库之jQuery示例
1.全选 反选 取消 相关知识点: - 选择器 - .prop $('#tb:checkbox').prop('checked'); 获取值 $('#tb:checkbox').prop('check ...
- 分布式锁 ----zookeeper实践 (排它锁)
排它锁概念: Exclusive Locks,被称为X锁,写锁,独占锁.如果事物T1对数据对象O1加上了排它锁,那么在整个加锁期间,只允许事务T1对O1进行读写操作,其他事务必须等到T1释放锁后才能进 ...
- hadoop(1)---hadoop的介绍和几种模式。
一.什么是hadoop? Hadoop软件库是一个开源框架,允许使用简单的编程模型跨计算机集群分布式处理大型数据集.它旨在从单个服务器扩展到数千台计算机,每台计算机都提供本地计算和存储.库本身不是依靠 ...
- java中 什么是反射?
JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法: 对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为java语言的反射 ...
- golang ssh 远程执行命令(有一些命令会报command not found)
func sshSession(user, password, host string, port int) (sshSession *ssh.Session, err error) { //参数: ...
- GCC编译流程及常用编辑命令
GCC 编译器在编译一个C语言程序时需要经过以下 4 步: 将C语言源程序预处理,生成.i文件. 预处理后的.i文件编译成为汇编语言,生成.s文件. 将汇编语言文件经过汇编,生成目标文件.o文件. 将 ...
- MediaPlayer: BufferQueue has been abandoned 解决方案
最近在做一个播放器,需要实现一个从小屏切换到全屏的效果,我用的是TextureView + MediaPlayer 的方式去实现,当需要切换成全屏时,我在 TextureView 的 onSurfac ...
- keras Model 3 共享的层
1 入门 2 多个输入和输出 3 共享层 考虑这样的一个问题:我们要判断连个tweet是否来源于同一个人. 首先我们对两个tweet进行处理,然后将处理的结构拼接在一起,之后跟一个逻辑回归,输出这两条 ...
- Docs-.NET-C#-指南-语言参考-预处理器指令:#else(C# 参考)
ylbtech-Docs-.NET-C#-指南-语言参考-预处理器指令:#else(C# 参考) 1.返回顶部 1. #else(C# 参考) 2015/07/20 #else 允许创建复合条件指令, ...