这是我参与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复制代码 |
本文转载自: 掘金