文档

https://gitee.com/baomidou/dynamic-datasource-spring-boot-starter/wikis/pages

maven

  1.  
    <dependency>
  2.  
    <groupId>com.baomidou</groupId>
  3.  
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
  4.  
    <version>2.5.7</version>
  5.  
    </dependency>

纯读写分离(mybatis环境)

场景:

  1. 在纯的读写分离环境,写操作全部是master,读操作全部是slave。
  2. 不想通过注解配置完成以上功能。

答:在mybatis环境下可以基于mybatis插件结合本数据源完成以上功能。 手动注入插件。

  1.  
    @Bean
  2.  
    public MasterSlaveAutoRoutingPlugin masterSlaveAutoRoutingPlugin(){
  3.  
    return new MasterSlaveAutoRoutingPlugin();
  4.  
    }

默认主库名称master,从库名称slave。

问题

我在配置好了之后,调试发现对数据库读的操作不得进入MasterSlaveAutoRoutingPlugin,而且进入了默认的库。只有写进入了MasterSlaveAutoRoutingPlugin中。当然也可以默认为从库,但是感觉就不是很好。

于是我自定义了一个aop切面来,来完成库的选择,代码如下:

  1.  
    import java.lang.reflect.Method;
  2.  
    import org.aspectj.lang.JoinPoint;
  3.  
    import org.aspectj.lang.annotation.After;
  4.  
    import org.aspectj.lang.annotation.Aspect;
  5.  
    import org.aspectj.lang.annotation.Before;
  6.  
    import org.aspectj.lang.annotation.Pointcut;
  7.  
    import org.aspectj.lang.reflect.MethodSignature;
  8.  
    import org.springframework.context.annotation.Lazy;
  9.  
    import org.springframework.core.annotation.Order;
  10.  
    import org.springframework.stereotype.Component;
  11.  
    import com.baomidou.dynamic.datasource.annotation.DS;
  12.  
    import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
  13.  
    import lombok.extern.java.Log;
  14.  
     
  15.  
    /**
  16.  
    * Copyright: Copyright (c) 2019
  17.  
    * <p> 说明:动态数据源配置 </P>
  18.  
    *
  19.  
    * @version: V1.0
  20.  
    * @author: BianPeng
  21.  
    *
  22.  
    */
  23.  
    @Aspect
  24.  
    @Component
  25.  
    @Order(0)
  26.  
    @Lazy(false)
  27.  
    @Log
  28.  
    public class DataSourceAop{
  29.  
     
  30.  
    private static final String MASTER = "master";
  31.  
     
  32.  
    private static final String SLAVE = "slave";
  33.  
     
  34.  
     
  35.  
    @Pointcut("execution(* com.buybit.power.service..*.*(..)) || execution(* com.baomidou.mybatisplus.extension.service..*.*(..))")
  36.  
    public void checkArgs() {
  37.  
    }
  38.  
     
  39.  
    // 这里切到你的方法目录
  40.  
    @Before("checkArgs()")
  41.  
    public void process(JoinPoint joinPoint) throws NoSuchMethodException, SecurityException {
  42.  
    String methodName = joinPoint.getSignature().getName();
  43.  
    if (methodName.startsWith("get")
  44.  
    || methodName.startsWith("count")
  45.  
    || methodName.startsWith("find")
  46.  
    || methodName.startsWith("list")
  47.  
    || methodName.startsWith("select")
  48.  
    || methodName.startsWith("check")
  49.  
    || methodName.startsWith("page")) {
  50.  
     
  51.  
    log.info("当前执行的库:"+SLAVE);
  52.  
    DynamicDataSourceContextHolder.push(SLAVE);
  53.  
    } else {
  54.  
    log.info("当前执行的库:"+MASTER);
  55.  
    DynamicDataSourceContextHolder.push(MASTER);
  56.  
    }
  57.  
    }
  58.  
    @After("checkArgs()")
  59.  
    public void afterAdvice(){
  60.  
    DynamicDataSourceContextHolder.clear();
  61.  
    }
  62.  
    }

但是发现,baomidou/dynamic-datasource自带的@DS没失去了着用,于是我把有@DS的类和方法排除掉,代码入下:

  1.  
    import java.lang.reflect.Method;
  2.  
    import org.aspectj.lang.JoinPoint;
  3.  
    import org.aspectj.lang.annotation.After;
  4.  
    import org.aspectj.lang.annotation.Aspect;
  5.  
    import org.aspectj.lang.annotation.Before;
  6.  
    import org.aspectj.lang.annotation.Pointcut;
  7.  
    import org.aspectj.lang.reflect.MethodSignature;
  8.  
    import org.springframework.context.annotation.Lazy;
  9.  
    import org.springframework.core.annotation.Order;
  10.  
    import org.springframework.stereotype.Component;
  11.  
    import com.baomidou.dynamic.datasource.annotation.DS;
  12.  
    import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
  13.  
    import lombok.extern.java.Log;
  14.  
     
  15.  
    /**
  16.  
    * Copyright: Copyright (c) 2019
  17.  
    * <p> 说明:动态数据源配置 </P>
  18.  
    *
  19.  
    * @version: V1.0
  20.  
    * @author: BianPeng
  21.  
    *
  22.  
    */
  23.  
    @Aspect
  24.  
    @Component
  25.  
    @Order(0)
  26.  
    @Lazy(false)
  27.  
    @Log
  28.  
    public class DataSourceAop{
  29.  
     
  30.  
    private static final String MASTER = "master";
  31.  
     
  32.  
    private static final String SLAVE = "slave";
  33.  
     
  34.  
     
  35.  
    @Pointcut("execution(* com.buybit.power.service..*.*(..)) || execution(* com.baomidou.mybatisplus.extension.service..*.*(..))")
  36.  
    public void checkArgs() {
  37.  
    }
  38.  
     
  39.  
    // 这里切到你的方法目录
  40.  
    @Before("checkArgs()")
  41.  
    public void process(JoinPoint joinPoint) throws NoSuchMethodException, SecurityException {
  42.  
    String methodName = joinPoint.getSignature().getName();
  43.  
    Class clazz = joinPoint.getTarget().getClass();
  44.  
    if(clazz.isAnnotationPresent(DS.class)){
  45.  
    //获取类上注解
  46.  
    return;
  47.  
    }
  48.  
     
  49.  
    String targetName = clazz.getSimpleName();
  50.  
    Class[] parameterTypes =
  51.  
    ((MethodSignature)joinPoint.getSignature()).getMethod().getParameterTypes();
  52.  
    Method methdo = clazz.getMethod(methodName,parameterTypes);
  53.  
    if (methdo.isAnnotationPresent(DS.class)) {
  54.  
    return;
  55.  
    }
  56.  
    if (methodName.startsWith("get")
  57.  
    || methodName.startsWith("count")
  58.  
    || methodName.startsWith("find")
  59.  
    || methodName.startsWith("list")
  60.  
    || methodName.startsWith("select")
  61.  
    || methodName.startsWith("check")
  62.  
    || methodName.startsWith("page")) {
  63.  
     
  64.  
    log.info("当前执行的库:"+SLAVE);
  65.  
    DynamicDataSourceContextHolder.push(SLAVE);
  66.  
    } else {
  67.  
    log.info("当前执行的库:"+MASTER);
  68.  
    DynamicDataSourceContextHolder.push(MASTER);
  69.  
    }
  70.  
    }
  71.  
    @After("checkArgs()")
  72.  
    public void afterAdvice(){
  73.  
    DynamicDataSourceContextHolder.clear();
  74.  
    }
  75.  
    }

这样可以让你有@DS的注解依然生效,而且也会根据方法名来自动切换数据源。

baomidou的dynamic-datasource读写分离实现和加入AOP根据方法名选择库的更多相关文章

  1. SSM/SSH框架的MySQL 读写分离实现的一种简单方法

    简介 MySQL已经是使用最为广泛的一种数据库,往往实际使用过程中,为实现高可用及高性能,项目会采用主丛复制的方式实现读写分离.MySQL本身支持复制,通过简单的配置即可实现一主多从的配置,具体实现可 ...

  2. 【EFCore框架】支持多数库 、支持读写分离框架、支持事务提交保存、跨库实现事务

    1.支持多数库: 数据库上下文实现 多数据支持: 2. 支持读写分离框架(支持多从库随机) 工作单元(以及仓储)实现读写分离 配置文件: 3. 支持事务提交保存 工作单元 实现事务数据统一提交保存 具 ...

  3. laravel(lumen)配置读写分离后,强制读主(写)库数据库,解决主从延迟问题

    在Model里面加上下面这句,强制读主(写)库数据库,解决主从延迟问题. public static function boot() { //清空从连接,会自动使用主连接 DB::connection ...

  4. Springboot + Mysql8实现读写分离

    在实际的生产环境中,为了确保数据库的稳定性,我们一般会给数据库配置双机热备机制,这样在master数据库崩溃后,slave数据库可以立即切换成主数据库,通过主从复制的方式将数据从主库同步至从库,在业务 ...

  5. 从零开始学 Java - Spring AOP 实现主从读写分离

    深刻讨论为什么要读写分离? 为了服务器承载更多的用户?提升了网站的响应速度?分摊数据库服务器的压力?就是为了双机热备又不想浪费备份服务器?上面这些回答,我认为都不是错误的,但也都不是完全正确的.「读写 ...

  6. JAVA-mysql读写分离插件介绍

    kingshard是一个由Go开发高性能MySQL Proxy项目,kingshard在满足基本的读写分离的功能上,致力于简化MySQL分库分表操作:能够让DBA通过kingshard轻松平滑地实现M ...

  7. Spring Boot2(四):使用Spring Boot多数据源实现读写分离

    前言 实际业务场景中,不可能只有一个库,所以就有了分库分表,多数据源的出现.实现了读写分离,主库负责增改删,从库负责查询.这篇文章将实现Spring Boot如何实现多数据源,动态数据源切换,读写分离 ...

  8. Mybatis多数据源读写分离(注解实现)

    #### Mybatis多数据源读写分离(注解实现) ------ 首先需要建立两个库进行测试,我这里使用的是master_test和slave_test两个库,两张库都有一张同样的表(偷懒,喜喜), ...

  9. 读写分离很难吗?springboot结合aop简单就实现了

    目录 前言 环境部署 开始项目 注意 參考: 前言 入职新公司到现在也有一个月了,完成了手头的工作,前几天终于有时间研究下公司旧项目的代码.在研究代码的过程中,发现项目里用到了Spring Aop来实 ...

  10. 原理解密 → Spring AOP 实现动态数据源(读写分离),底层原理是什么

    开心一刻 女孩睡醒玩手机,收到男孩发来一条信息:我要去跟我喜欢的人表白了! 女孩的心猛的一痛,回了条信息:去吧,祝你好运! 男孩回了句:但是我没有勇气说不来,怕被打! 女孩:没事的,我相信你!此时女孩 ...

随机推荐

  1. markdown的html优雅使用语法(2024/10/10guixiang原创)

    一:图片部分 第一范式 图 2 全字段排序 <center> <img style="border-radius: 0.3125em; box-shadow: 0 2px ...

  2. 云原生周刊:Artifact Hub 成为 CNCF 孵化项目|2024.9.23

    开源项目推荐 Coroot Coroot 是一个开源监控工具,旨在为云原生应用提供可观察性.它通过整合指标.日志和追踪信息,专注于提供应用性能的洞察. DirectPV DirectPV 是一个开源项 ...

  3. "开源"是什么?为啥这么火?一定免费吗?

    ​ 在科技快速发展的今天,"开源"一词频频出现在我们的视野中.究竟什么是开源?为何它能在技术圈引发如此热潮? 开源软件到底有什么魅力?它是如何改变软件开发和使用的方式的?开源软件是 ...

  4. 欢迎来到IoT解忧杂货铺

    这是一间特殊的杂货铺 门面不大,却包罗万物 如果你也遇到一些烦恼 欢迎来到,IoT解忧杂货铺 解忧秘方·工业 厂里的几十台设备真让人头疼 协议种类太多太复杂 设备没法全联网 产线故障了也不知道 自己出 ...

  5. Linux利用scp命令上传下载文件

    scp是secure copy的简写,用于在 Linux 下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器. scp传输是加密的,可能会稍微影响一下速度.当你服务 ...

  6. docker网络管理--项目三

    一.Docker网络概念 1.网络驱动 Docker 网络子系统使用可插拔的驱动,默认情况下有多个驱动程序,并提供核心联网功能. bridge:桥接网络,这是默认的网络驱动程序(不指定驱动程序创建的容 ...

  7. Minio安装以及使用

    Minio介绍 MinIO 是一个基于Apache License v2.0开源协议的对象存储服务.适合于存储大容量非结构化的数据,例如图片.视频.日志文件.备份数据和容器/虚拟机镜像等,而一个对象文 ...

  8. STM32F103RCT6搭配“ST_LINK V2 √RoHS 'A 2023 04'”在CubeIDE中下载程序到单片机

    一.请参考本站大佬文章进行接线: ST_LINK V2接口和连接方式 二.步骤: 到此,大功告成. 小手点赞,水逆退散!!!

  9. 前端性能优化:使用 Web Workers 实现轮询

    // pollWorker.js import { Base64 } from 'js-base64'; import RsaAndAes from '~/composables/RsaAndAes' ...

  10. Cargo deny安装指路

    本博客所有文章除特别声明外,均采用CC BY-NC-SA 4.0许可协议.转载请注明来自 唯你 简介 cargo deny 是一个 Rust 工具,用于检查项目依赖项的许可证.安全性和其他合规性问题. ...