baomidou的dynamic-datasource读写分离实现和加入AOP根据方法名选择库
2019-10-22 12:05
2301 查看
文档
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插件结合本数据源完成以上功能。 手动注入插件。
@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的类和方法排除掉,代码入下:
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(); 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); } } @After("checkArgs()") public void afterAdvice(){ DynamicDataSourceContextHolder.clear(); } }
这样可以让你有@DS的注解依然生效,而且也会根据方法名来自动切换数据源。
相关文章推荐
- Spring boot整合dynamic-datasource实现多数据源的读写分离
- html <select> <option> 实现根据选择不同的option,调用不同的方法功能
- 拦截器、执行-拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是AOP的一种实现策略。-by小雨
- C++ Builder下三种UDP通信实现方法的比较 选择自 findheart 的 Blog
- 使用反射实现根据名称动态创建窗体的几种方法。
- dojo的connect方法使用与源代码剖析(在JavaScript里实现类似AOP的效果)
- 使用反射实现根据名称动态创建窗体的几种方法。
- 左边select内容选择到右边select内容里面的js实现方法(可以多选和全选)
- dojo的connect方法使用与源代码剖析(在JavaScript里实现类似AOP的效果)
- 关于JSP中单击任意标签弹出文件选择框(<input type="file"/>)的实现方法
- 关于在GridView模版里添加DropDownList实现根据下拉列表的不同选择gridview根据条件筛选显示。
- GridView加入CheckBox实现全选,跨页CheckBox选择
- table+webusercontrol实现左边treeview,右边根据节点选择不同加载不同页面
- Interposer - 实现AOP的又一个方法...
- spring 实现aop的三种方法
- List<T>泛型数组API自带的Sort() 排序方法根据自定义排序实现
- Autofac整合Castle.DynamicProxy实现AOP
- DataGrid中加入CheckBox,并实现单选 选择自 listhome 的 Blog
- 使用反射实现根据名称动态创建窗体的几种方法
- XHTMLCSS的静态页面实现多风格选择的方法