baomidou的dynamic-datasource读写分离实现和加入AOP根据方法名选择库
文档
https://gitee.com/baomidou/dynamic-datasource-spring-boot-starter/wikis/pages
maven
-
<dependency>
-
<groupId>com.baomidou</groupId>
-
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
-
<version>2.5.7</version>
-
</dependency>
纯读写分离(mybatis环境)
场景:
- 在纯的读写分离环境,写操作全部是master,读操作全部是slave。
- 不想通过注解配置完成以上功能。
答:在mybatis环境下可以基于mybatis插件结合本数据源完成以上功能。 手动注入插件。
-
-
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
-
*
-
*/
-
-
-
-
-
-
public class DataSourceAop{
-
-
private static final String MASTER = "master";
-
-
private static final String SLAVE = "slave";
-
-
-
-
public void 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);
-
}
-
}
-
-
public void afterAdvice(){
-
DynamicDataSourceContextHolder.clear();
-
}
-
}
但是发现,baomidou/dynamic-datasource自带的@DS没失去了着用,于是我把有@DS的类和方法排除掉,代码入下:
-
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
-
*
-
*/
-
-
-
-
-
-
public class DataSourceAop{
-
-
private static final String MASTER = "master";
-
-
private static final String SLAVE = "slave";
-
-
-
-
public void checkArgs() {
-
}
-
-
// 这里切到你的方法目录
-
-
public void process(JoinPoint joinPoint) throws NoSuchMethodException, SecurityException {
-
String methodName = joinPoint.getSignature().getName();
-
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)) {
-
return;
-
}
-
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);
-
}
-
}
-
-
public void afterAdvice(){
-
DynamicDataSourceContextHolder.clear();
-
}
-
}
这样可以让你有@DS的注解依然生效,而且也会根据方法名来自动切换数据源。