这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战
背景
当数据量过大时候,对单表进行更新、查询的操作有时候会导致锁表,让读写速度跟不上,一个页面就要2-3秒,这就需要使用读写分离。
很多应用的数据库读操作比写操作更加密集,而且查询条件相对复杂,数据库的大部分性能消耗在查询操作上了。为保证数据库数据的一致性,我们要求所有对于数据库的更新操作都是针对主数据库的,读操作从数据库来进行。
代码
配置文件
增加双数据源的数据库配置
1  | yml复制代码spring:  | 
自定义注解
自定义数据源key的注解,value为数据源key
1  | java复制代码@Retention(RetentionPolicy.RUNTIME)  | 
数据源key设置
1  | java复制代码@Slf4j  | 
动态数据源类
1  | java复制代码public class DynamicDataSource extends AbstractRoutingDataSource {  | 
数据源配置类
定义双数据源的key和bean对应关系
1  | java复制代码@Configuration  | 
自定义切面
切面实现方法通过注解中的value进行切换不同数据源。
1  | java复制代码@Aspect  | 
使用注解
在方法上面用自定义的数据源注解声明数据源,就可以实现不同方法,不同数据源调用。
1  | java复制代码 @DataSource("dataSource1")  | 
原理解析
通过AOP对方法进行切面,将注解中的value获取到,并设置为数据源Key,通过数据源配置类,拿到数据源对应的数据库bean,进而实现数据源切换。
AbstractRoutingDataSource
AbstractRoutingDataSource继承AbstractDataSource,如果声明一个类DynamicDataSource继承AbstractRoutingDataSource后,DynamicDataSource本身就相当于一种数据源。所以AbstractRoutingDataSource必然有getConnection()方法获取数据库连接。
大致流程为,通过determineCurrentLookupKey方法获取一个key,通过key从resolvedDataSources中获取数据源DataSource对象。determineCurrentLookupKey()是个抽象方法,需要继承AbstractRoutingDataSource的类实现;而resolvedDataSources是一个Map<Object, DataSource>,里面应该保存当前所有可切换的数据源。
1  | java复制代码  | 
本文转载自: 掘金