千家信息网

spring-boot结合AOP实现数据源动态配置的方法

发表于:2025-01-23 作者:千家信息网编辑
千家信息网最后更新 2025年01月23日,本篇内容主要讲解"spring-boot结合AOP实现数据源动态配置的方法",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"spring-boot结合AOP实
千家信息网最后更新 2025年01月23日spring-boot结合AOP实现数据源动态配置的方法

本篇内容主要讲解"spring-boot结合AOP实现数据源动态配置的方法",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"spring-boot结合AOP实现数据源动态配置的方法"吧!

Spring-Boot+AOP方式实现多数据源切换

设计总体思路:Spring-Boot+AOP方式实现多数据源切换,继承AbstractRoutingDataSource实现数据源动态的获取,在service层使用注解指定数据源。

一、多数据源配置

在application.properties中,我们的配置是这样的

#主数据源druid.master.url=jdbc:mysql://url/masterdb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNulldruid.master.username=xxxdruid.master.password=123druid.master.driver-class-name=com.mysql.jdbc.Driverdruid.master.max-wait=5000druid.master.max-active=100druid.master.test-on-borrow=truedruid.master.validation-query=SELECT 1#从数据源druid.slave.url=jdbc:mysql://url/slavedb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNulldruid.slave.username=xxxdruid.slave.password=123druid.slave.driver-class-name=com.mysql.jdbc.Driverdruid.slave.max-wait=5000druid.slave.max-active=100druid.slave.test-on-borrow=truedruid.slave.validation-query=SELECT 1

读取配置

                                                                                                                                                                        
二、动态数据源

spring为我们提供了AbstractRoutingDataSource,即带路由的数据源。继承后我们需要实现它的determineCurrentLookupKey(),该方法用于自定义实际数据源名称的路由选择方法,由于我们将信息保存到了ThreadLocal中,所以只需要从中拿出来即可。

public class DynamicDataSource extends AbstractRoutingDataSource {    private Logger logger = LoggerFactory.getLogger(this.getClass());    @Override    protected Object determineCurrentLookupKey() {        String dataSource = JdbcContextHolder.getDataSource();        logger.info("数据源为{}",dataSource);        return dataSource;    }}
三. 数据源动态切换类

动态数据源切换是基于AOP的,所以我们需要声明一个AOP切面,并在切面前做数据源切换,切面完成后移除数据源名称。

@Aspect@Order(1)   //设置AOP执行顺序(需要在事务之前,否则事务只发生在默认库中)@Componentpublic class DataSourceAspect {    private Logger logger = LoggerFactory.getLogger(this.getClass());    //切点    @Pointcut("execution(* com.xxx.service.*.*(..))")    public void aspect() { }    @Before("aspect()")    private void before(JoinPoint point) {        Object target = point.getTarget();        String method = point.getSignature().getName();        Class classz = target.getClass();// 获取目标类        Class[] parameterTypes = ((MethodSignature) point.getSignature())                .getMethod().getParameterTypes();        try {            Method m = classz.getMethod(method, parameterTypes);            if (m != null && m.isAnnotationPresent(MyDataSource.class)) {                MyDataSource data = m.getAnnotation(MyDataSource.class);                logger.info("method :{},datasource:{}",m.getName() ,data.value().getName());                JdbcContextHolder.putDataSource(data.value().getName());// 数据源放到当前线程中            }        } catch (Exception e) {            logger.error("get datasource error ",e);            //默认选择master            JdbcContextHolder.putDataSource(DataSourceType.Master.getName());// 数据源放到当前线程中        }    }    @AfterReturning("aspect()")    public void after(JoinPoint point) {        JdbcContextHolder.clearDataSource();    }}
四、数据源管理类
public class JdbcContextHolder {    private final static ThreadLocal local = new ThreadLocal<>();    public static void putDataSource(String name) {        local.set(name);    }    public static String getDataSource() {        return local.get();    }    public static void clearDataSource() {        local.remove();    }}
五、数据源注解和枚举

我们切换数据源时,一般都是在调用具体接口的方法前实现,所以我们定义一个方法注解,当AOP检测到方法上有该注解时,根据注解中value对应的名称进行切换。

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface MyDataSource {    DataSourceType value();}

public enum  DataSourceType {    // 主表    Master("master"),    // 从表    Slave("slave");    private String name;    private DataSourceType(String name) {        this.name = name;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}
六、切点注解

由于我们的动态数据源配置了默认库,所以如果方法是操作默认库的可以不需要注解,如果要操作非默认数据源,我们需要在方法上添加@MyDataSource("数据源名称")注解,这样就可以利用AOP实现动态切换了

@Componentpublic class xxxServiceImpl {    @Resource    private XxxMapperExt xxxMapperExt;    @MyDataSource(value= DataSourceType.Slave)    public List getAll(){        return xxxMapperExt.getAll();    }}

原文链接:

http://tech.dianwoda.com/2018/03/28/spring-boot-aopfang-shi-shi-xian-duo-shu-ju-yuan-qie-huan/

到此,相信大家对"spring-boot结合AOP实现数据源动态配置的方法"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

0