产生原因
- 代理模式中真实对象方法调用方法不会走代理对象,因此类似于@DS注解使用AOP切面进行数据源的切换,在方法调用方法是不会成功的
解决办法
- 原理:通过修改本地线程变量中的数据源栈,来进行数据源的切换
- 本实例使用@DS,其他动态数据源(自定义动态数据源)逻辑类似
- 封装的手动切换数据源工具类
- 自定义一个SmallConsumer注解,主要是填充无参回调函数接口
@FunctionalInterface
public interface SmallConsumer {
void accept();
default SmallConsumer andThen(SmallConsumer after) {
Objects.requireNonNull(after);
return () -> {
accept();
after.accept();
};
}
}
- 编写手动切换数据源工具类,实际就是操作本地线程变量
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
@Component
@Slf4j
public class ChooseDsUtil {
private final static String masterDB = "master";
private final static String slaveDB = "slave";
@Resource
private ApplicationContext applicationContext;
public void masterExec(SmallConsumer execConsumer) {
try {
DynamicDataSourceContextHolder.push(masterDB);
execConsumer.accept();
} finally {
DynamicDataSourceContextHolder.poll();
}
}
public void slaveExec(SmallConsumer execConsumer) {
try {
DynamicDataSourceContextHolder.push(slaveDB);
execConsumer.accept();
} finally {
DynamicDataSourceContextHolder.poll();
}
}
public <T> T getAopBean(Class<T> tClass) {
return applicationContext.getBean(tClass);
}
}
- 注意:不管是自动切换数据源还是手动切换数据源,切换执行完毕后都不会自动切换回来,比如:在更新逻辑中,先切换到读库进行数据获取,然后再数据处理,最后将处理后的数据更新到写库中,此时在写之前需要切换数据源到写库