【Spring Boot】Spring Boot之使用AOP实现数据库多数据源自动切换
一、添加maven坐标
<!-- aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- jdbc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.</version>
</dependency>
二、加入Mybtis配置类(方便测试)
/**
* @author zhangboqing
* @date 2018/8/3
*
* Mybatis配置
*/
@Configuration
@MapperScan(basePackages = {"com.zbq.springbootdemo.dao"}, sqlSessionFactoryRef = "sqlSessionFactory")
//或者直接在Mapper类上面添加注解@Mapper,建议使用上面那种,不然每个mapper加个注解也挺麻烦的
public class MyBatisConfig { }
三、加入多数据源配置
1)修改application.yml添加数据库配置属性
spring:
datasource:
primary:
hikari:
connection-test-query: SELECT FROM DUAL
connection-timeout:
maximum-pool-size:
max-lifetime:
minimum-idle:
validation-timeout:
idle-timeout:
connection-init-sql: SET NAMES utf8mb4
jdbc-url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull
username: root
password:
driver-class-name: com.mysql.jdbc.Driver
secondary:
hikari:
connection-test-query: SELECT FROM DUAL
connection-timeout:
maximum-pool-size:
max-lifetime:
minimum-idle:
validation-timeout:
idle-timeout:
connection-init-sql: SET NAMES utf8mb4
jdbc-url: jdbc:mysql://localhost:3326/test?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull
username: root
password:
driver-class-name: com.mysql.jdbc.Driver
2)添加DataSourceConfig配置类(自定义DataSource数据源)
/**
* @author zhangboqing
* @date 2019-11-17
*/
@Configuration
// 自定义数据源一定要排除SpringBoot自动配置数据源,不然会出现循环引用的问题,The dependencies of some of the beans in the application context form a cycle
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class DataSourceConfig { @Bean(name = "primary")
@ConfigurationProperties(prefix = "spring.datasource.primary.hikari")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
} @Bean(name = "secondary")
@ConfigurationProperties(prefix = "spring.datasource.secondary.hikari")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
} /**
* 动态数据源
* 通过AOP+注解实现动态切换
*
* @return
*/
@Primary
@Bean(name = "dynamicDataSource")
public DataSource dataSource() {
DynamicDataSourceRouter dynamicDataSource = new DynamicDataSourceRouter();
// 默认数据源
dynamicDataSource.setDefaultTargetDataSource(primaryDataSource());
// 配置多数据源
Map<Object, Object> dataSourceMap = new HashMap();
dataSourceMap.put("primary", primaryDataSource());
dataSourceMap.put("secondary", secondaryDataSource());
dynamicDataSource.setTargetDataSources(dataSourceMap);
return dynamicDataSource;
} /**
* 配置@Transactional注解事物
*
* @return
*/
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
} }
/**
* @author zhangboqing
* @date 2019-11-17
*/
public class DynamicDataSourceRouter extends AbstractRoutingDataSource{
@Override
protected Object determineCurrentLookupKey() {
return DataSourceNameContextHolder.getDataSourceName();
} @Override
public void setLogWriter(PrintWriter pw) throws SQLException {
super.setLogWriter(pw);
}
}
3)定义 @DataSourceName注解(用于指定sql对应的数据源)
/**
* @author zhangboqing
* @date 2019-11-17
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface DataSourceName { /**
* 指定数据源名称
* @return dataSourceName
*/
String value() default "primary";
}
4)定义DataSourceNameContextHolder类(使用ThreadLocal存放当前线程持有的数据源名称)
/**
* @author zhangboqing
* @date 2019-11-17
*/
@Slf4j
public class DataSourceNameContextHolder { private static final ThreadLocal<String> dataSourceNameContextHolder = new NamedThreadLocal<>("DataSourceContext"); /** 默认数据源名称 */
public static final String DEFAULT_DATASOURCE_NAME = "primary"; public static void setDataSourceName(String dataSourceName) {
log.info("切换到[{}]数据源", dataSourceName);
dataSourceNameContextHolder.set(dataSourceName);
} public static String getDataSourceName() { return dataSourceNameContextHolder.get() != null ? dataSourceNameContextHolder.get() : DEFAULT_DATASOURCE_NAME;
} public static void resetDataSourceName() {
dataSourceNameContextHolder.remove();
}
}
5)定义DynamicDataSourceAspect切面类(通过AOP的方式拦截指定注解实现数据源切换)
/**
* @author zhangboqing
* @date 2019-11-17
*/
@Aspect
@Component
public class DynamicDataSourceAspect { @Before("@annotation(dataSourceName)")
public void beforeSwitchDataSource(DataSourceName dataSourceName){
// 切换数据源
DataSourceNameContextHolder.setDataSourceName(dataSourceName.value());
} @After("@annotation(com.zbq.springbootdemo.config.multidatasource.DataSourceName)")
public void afterSwitchDataSource(){
DataSourceNameContextHolder.resetDataSourceName();
}
}
四、添加测试
1)在Mybtis配置类指定的包下定义一个Dao类并使用注解指定数据源
/**
* @author zhangboqing
* @date 2019-11-21
*/
@Repository
public interface UserDao { @DataSourceName("secondary")
@Select("select * from user order by create_time desc limit 1 ")
public User getNewstOne(); // 默认是primary,所以可以不指定
// @DataSourceName("primary")
@Select("select * from user order by create_time desc limit 1 ")
public User getNewstOne2();
}
2)定义测试类执行
/**
* @author zhangboqing
* @date 2019-11-21
*/
@SpringBootTest
@Slf4j
class UserServiceImplTest { @Autowired
private UserDao userDao; @Test
void getNewestOne() {
User newestOne = userDao.getNewstOne();
User newestOne2 = userDao.getNewstOne2();
log.info(newestOne.toString());
log.info(newestOne2.toString());
}
}
3)执行结果可知多数据源生效,同样的sql查询结果分别来自于两个库
-- ::51.124 INFO --- [ main] c.z.s.service.UserServiceImplTest : User(uid=, phone=, createTime=null, updateTime=null)
-- ::51.124 INFO --- [ main] c.z.s.service.UserServiceImplTest : User(uid=, phone=, createTime=null, updateTime=null)
【Spring Boot】Spring Boot之使用AOP实现数据库多数据源自动切换的更多相关文章
- 四、Spring Boot 多数据源 自动切换
实现案例场景: 某系统除了需要从自己的主要数据库上读取和管理数据外,还有一部分业务涉及到其他多个数据库,要求可以在任何方法上可以灵活指定具体要操作的数据库.为了在开发中以最简单的方法使用,本文基于注解 ...
- Spring Boot 多数据源自动切换
在Spring Boot中使用单数据源的配置很简单,我们简单回忆下:只需要在application.properties进行基本的连接配置,在pom.xml引入基本的依赖即可. 那么多数据源的原理呢? ...
- 43. Spring Boot动态数据源(多数据源自动切换)【从零开始学Spring Boot】
[视频&交流平台] àSpringBoot视频 http://study.163.com/course/introduction.htm?courseId=1004329008&utm ...
- (43). Spring Boot动态数据源(多数据源自动切换)【从零开始学Spring Boot】
在上一篇我们介绍了多数据源,但是我们会发现在实际中我们很少直接获取数据源对象进行操作,我们常用的是jdbcTemplate或者是jpa进行操作数据库.那么这一节我们将要介绍怎么进行多数据源动态切换.添 ...
- Spring标签@Aspect-实现面向方向编程(@Aspect的多数据源自动加载)——SKY
从Spring 2.0开始,可以使用基于schema及@AspectJ的方式来实现AOP.由于@Aspect是基于注解的,因此要求支持注解的5.0版本以上的JDK. 环境要求: 1. mybit ...
- Spring Boot 动态数据源(多数据源自动切换)
本文实现案例场景: 某系统除了需要从自己的主要数据库上读取和管理数据外,还有一部分业务涉及到其他多个数据库,要求可以在任何方法上可以灵活指定具体要操作的数据库. 为了在开发中以最简单的方法使用,本文基 ...
- 22. Spring Boot 动态数据源(多数据源自动切换)
转自:https://blog.csdn.net/catoop/article/details/50575038
- Spring Boot -- Spring AOP原理及简单实现
一.AOP基本概念 什么是AOP,AOP英语全名就是Aspect oriented programming,字面意思就是面向切面编程.面向切面的编程是对面向对象编程的补充,面向对象的编程核心模块是类, ...
- 【Spring】关于Boot应用中集成Spring Security你必须了解的那些事
Spring Security Spring Security是Spring社区的一个顶级项目,也是Spring Boot官方推荐使用的Security框架.除了常规的Authentication和A ...
随机推荐
- MySql5.7InnoDB全文索引(针对中文搜索)
1.ngram and MeCab full-text parser plugins 全文检索在MySQL里面很早就支持了,只不过一直以来只支持英文.缘由是他从来都使用空格来作为分词的分隔符,而对于中 ...
- 在springboot中使用redis缓存,将缓存序列化为json格式的数据
背景 在springboot中使用redis缓存结合spring缓存注解,当缓存成功后使用gui界面查看redis中的数据 原因 springboot缓存默认的序列化是jdk提供的 Serializa ...
- Mysql查询数据库状态及信息
使用MySQL时,需要了解当前数据库的情况,例如当前的数据库大小.字符集.用户等等.下面总结了一些查看数据库相关信息的命令 1:查看显示所有数据库 mysql> show databases; ...
- 【day03】Xhtml
一.HTML公共属性 1. title 提示 2. class 3. id 4. style 说明:除了 html,head,body,link,meta外其他标记都可使用的属性 二.表单 1 ...
- Bootstrap-table 单元格合并 、表头合并
1.页面引入js/css @*1.Jquery组件引用*@ <script src="~/Scripts/jquery-1.10.2.js"></script&g ...
- [LeetCode] 663. Equal Tree Partition 划分等价树
Given a binary tree with n nodes, your task is to check if it's possible to partition the tree to tw ...
- [LeetCode] 352. Data Stream as Disjoint Intervals 分离区间的数据流
Given a data stream input of non-negative integers a1, a2, ..., an, ..., summarize the numbers seen ...
- [LeetCode] 43. Multiply Strings 字符串相乘
Given two non-negative integers num1 and num2represented as strings, return the product of num1 and ...
- 搭建Jena Fuseki并执行SPARQL查询
1. 下载Jena Fuseki:http://jena.apache.org/download/index.cgi 2. 运行服务 windows解压后双击fuseki-server.bat lin ...
- C# 迭代器与yield关键字
迭代器模式是设计模式的一种,因为其运用的普遍性,很多语言都有内嵌的原生支持 在.NET中,迭代器模式是通过IEnumerator.IEnumerable两个接口(有非泛型和泛型2种版本)来封装的 迭代 ...