天天看點

baomidou的dynamic-datasource讀寫分離實作和加入AOP根據方法名選擇庫

  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. * Copyright: Copyright (c) 2019
  16. * <p> 說明:動态資料源配置 </P>
  17. *
  18. * @version: V1.0
  19. * @author: BianPeng
  20. */
  21. @Aspect
  22. @Component
  23. @Order(0)
  24. @Lazy(false)
  25. @Log
  26. public class DataSourceAop{
  27. private static final String MASTER = "master";
  28. private static final String SLAVE = "slave";
  29. @Pointcut("execution(* com.buybit.power.service..*.*(..)) || execution(* com.baomidou.mybatisplus.extension.service..*.*(..))")
  30. public void checkArgs() {
  31. // 這裡切到你的方法目錄
  32. @Before("checkArgs()")
  33. public void process(JoinPoint joinPoint) throws NoSuchMethodException, SecurityException {
  34. String methodName = joinPoint.getSignature().getName();
  35. if (methodName.startsWith("get")
  36. || methodName.startsWith("count")
  37. || methodName.startsWith("find")
  38. || methodName.startsWith("list")
  39. || methodName.startsWith("select")
  40. || methodName.startsWith("check")
  41. || methodName.startsWith("page")) {
  42. log.info("目前執行的庫:"+SLAVE);
  43. DynamicDataSourceContextHolder.push(SLAVE);
  44. } else {
  45. log.info("目前執行的庫:"+MASTER);
  46. DynamicDataSourceContextHolder.push(MASTER);
  47. @After("checkArgs()")
  48. public void afterAdvice(){
  49. DynamicDataSourceContextHolder.clear();

但是發現,​​baomidou/dynamic-datasource​​自帶的@DS沒失去了着用,于是我把有@DS的類和方法排除掉,代碼入下:

  1. Class clazz = joinPoint.getTarget().getClass();
  2. if(clazz.isAnnotationPresent(DS.class)){
  3. //擷取類上注解
  4. return;
  5. String targetName = clazz.getSimpleName();
  6. Class[] parameterTypes =
  7. ((MethodSignature)joinPoint.getSignature()).getMethod().getParameterTypes();
  8. Method methdo = clazz.getMethod(methodName,parameterTypes);
  9. if (methdo.isAnnotationPresent(DS.class)) {

這樣可以讓你有@DS的注解依然生效,而且也會根據方法名來自動切換資料源。