189 8069 5689

SpringBoot中AOP方式实现多数据源切换的示例分析

小编给大家分享一下SpringBoot中AOP方式实现多数据源切换的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!

目前创新互联建站已为千余家的企业提供了网站建设、域名、虚拟空间、绵阳服务器托管、企业网站设计、梁子湖网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。

设计总体思路

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

步骤

一、多数据源配置

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

#主数据源
druid.master.url=jdbc:MySQL://url/masterdb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull
druid.master.username=xxx
druid.master.password=123
druid.master.driver-class-name=com.mysql.jdbc.Driver
druid.master.max-wait=5000
druid.master.max-active=100
druid.master.test-on-borrow=true
druid.master.validation-query=SELECT 1

#从数据源
druid.slave.url=jdbc:mysql://url/slavedb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull
druid.slave.username=xxx
druid.slave.password=123
druid.slave.driver-class-name=com.mysql.jdbc.Driver
druid.slave.max-wait=5000
druid.slave.max-active=100
druid.slave.test-on-borrow=true
druid.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执行顺序(需要在事务之前,否则事务只发生在默认库中)
@Component
public 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实现动态切换了

@Component
public class xxxServiceImpl {
  @Resource
  private XxxMapperExt xxxMapperExt;

  @MyDataSource(value= DataSourceType.Slave)
  public List getAll(){
    return xxxMapperExt.getAll();
  }
}

看完了这篇文章,相信你对“SpringBoot中AOP方式实现多数据源切换的示例分析”有了一定的了解,如果想了解更多相关知识,欢迎关注创新互联行业资讯频道,感谢各位的阅读!


当前题目:SpringBoot中AOP方式实现多数据源切换的示例分析
URL标题:http://cdxtjz.cn/article/pggcji.html

联系我们

您好HELLO!
感谢您来到成都网站建设公司,若您有合作意向,请您为我们留言或使用以下方式联系我们, 我们将尽快给你回复,并为您提供真诚的设计服务,谢谢。
  • 电话:028- 86922220 18980695689
  • 商务合作邮箱:631063699@qq.com
  • 合作QQ: 532337155
  • 成都网站设计地址:成都市青羊区锣锅巷31号五金站写字楼6楼

小谭建站工作室

成都小谭网站建设公司拥有多年以上互联网从业经验的团队,始终保持务实的风格,以"帮助客户成功"为已任,专注于提供对客户有价值的服务。 我们已为众企业及上市公司提供专业的网站建设服务。我们不只是一家网站建设的网络公司;我们对营销、技术、管理都有自己独特见解,小谭建站采取“创意+综合+营销”一体化的方式为您提供更专业的服务!

小谭观点

相对传统的成都网站建设公司而言,小谭是互联网中的网站品牌策划,我们精于企业品牌与互联网相结合的整体战略服务。
我们始终认为,网站必须注入企业基因,真正使网站成为企业vi的一部分,让整个网站品牌策划体系变的深入而持久。