- <dependency>
- <groupId>com.baomidou</groupId>
- <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
- <version>2.5.7</version>
- </dependency>
純讀寫分離(mybatis環境)
場景:
- 在純的讀寫分離環境,寫操作全部是master,讀操作全部是slave。
- 不想通過注解配置完成以上功能。
答:在mybatis環境下可以基于mybatis插件結合本資料源完成以上功能。 手動注入插件。
- @Bean
- public MasterSlaveAutoRoutingPlugin masterSlaveAutoRoutingPlugin(){
- return new MasterSlaveAutoRoutingPlugin();
- }
預設主庫名稱master,從庫名稱slave。
問題
我在配置好了之後,調試發現對資料庫讀的操作不得進入MasterSlaveAutoRoutingPlugin,而且進入了預設的庫。隻有寫進入了MasterSlaveAutoRoutingPlugin中。當然也可以預設為從庫,但是感覺就不是很好。
于是我自定義了一個aop切面來,來完成庫的選擇,代碼如下:
- import java.lang.reflect.Method;
- import org.aspectj.lang.JoinPoint;
- import org.aspectj.lang.annotation.After;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Before;
- import org.aspectj.lang.annotation.Pointcut;
- import org.aspectj.lang.reflect.MethodSignature;
- import org.springframework.context.annotation.Lazy;
- import org.springframework.core.annotation.Order;
- import org.springframework.stereotype.Component;
- import com.baomidou.dynamic.datasource.annotation.DS;
- import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
- import lombok.extern.java.Log;
- /**
- * Copyright: Copyright (c) 2019
- * <p> 說明:動态資料源配置 </P>
- *
- * @version: V1.0
- * @author: BianPeng
- */
- @Aspect
- @Component
- @Order(0)
- @Lazy(false)
- @Log
- public class DataSourceAop{
- private static final String MASTER = "master";
- private static final String SLAVE = "slave";
- @Pointcut("execution(* com.buybit.power.service..*.*(..)) || execution(* com.baomidou.mybatisplus.extension.service..*.*(..))")
- public void checkArgs() {
- // 這裡切到你的方法目錄
- @Before("checkArgs()")
- public void process(JoinPoint joinPoint) throws NoSuchMethodException, SecurityException {
- String methodName = joinPoint.getSignature().getName();
- if (methodName.startsWith("get")
- || methodName.startsWith("count")
- || methodName.startsWith("find")
- || methodName.startsWith("list")
- || methodName.startsWith("select")
- || methodName.startsWith("check")
- || methodName.startsWith("page")) {
- log.info("目前執行的庫:"+SLAVE);
- DynamicDataSourceContextHolder.push(SLAVE);
- } else {
- log.info("目前執行的庫:"+MASTER);
- DynamicDataSourceContextHolder.push(MASTER);
- @After("checkArgs()")
- public void afterAdvice(){
- DynamicDataSourceContextHolder.clear();
但是發現,baomidou/dynamic-datasource自帶的@DS沒失去了着用,于是我把有@DS的類和方法排除掉,代碼入下:
- Class clazz = joinPoint.getTarget().getClass();
- if(clazz.isAnnotationPresent(DS.class)){
- //擷取類上注解
- return;
- String targetName = clazz.getSimpleName();
- Class[] parameterTypes =
- ((MethodSignature)joinPoint.getSignature()).getMethod().getParameterTypes();
- Method methdo = clazz.getMethod(methodName,parameterTypes);
- if (methdo.isAnnotationPresent(DS.class)) {
這樣可以讓你有@DS的注解依然生效,而且也會根據方法名來自動切換資料源。