zoukankan      html  css  js  c++  java
  • baomidou的dynamic-datasource读写分离实现和加入AOP根据方法名选择库

    文档

    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的注解依然生效,而且也会根据方法名来自动切换数据源。

  • 相关阅读:
    推自己的镜像到网易云
    supervisord常见问题
    supervisord的配置
    一文解读SDN (转)
    一文解读ZooKeeper (转)
    使用 Docker 和 Nginx 打造高性能的二维码服务 (转)
    一文解读Docker (转)
    一文解读分布式架构 (转)
    一文解读分布式事务 (转)
    一文读懂工业大数据 (转)
  • 原文地址:https://www.cnblogs.com/exmyth/p/14296722.html
Copyright © 2011-2022 走看看