美文网首页
SpringBoot MySQL 多数据源配置

SpringBoot MySQL 多数据源配置

作者: 赛亚人之神 | 来源:发表于2019-04-26 15:05 被阅读0次

通过自定义注解,AOP,AbstractRoutingDataSource 实现

  1. 定义 DataSource 注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface DataSource {

  String value() default "slave";
}
  1. 设置AOP: DynamicDataSourceAspect 动态拦截注解 - 设置数据源
@Aspect
@Component
@Slf4j
public class DynamicDataSourceAspect {

  @Before("@annotation(com.linlong.back.core.annotation.DataSource)")
  public void beforeSwitch(JoinPoint point) {

    //获得当前访问的class
    Class<?> clazz = point.getTarget().getClass();

    //获得访问的方法名
    String methodName = point.getSignature().getName();

    // 得到方法的参数的类型
    Class[] argClass = ((MethodSignature) point.getSignature()).getParameterTypes();

    String dataSource = DataSourceContextHolder.DEFAULT_DATABASE;

    try {
      // 获取访问的方法对象
      Method method = clazz.getMethod(methodName, argClass);

      if (method.isAnnotationPresent(DataSource.class)) {
        DataSource annotation = method.getAnnotation(DataSource.class);

        dataSource = annotation.value();
      }
    } catch (NoSuchMethodException e) {
      log.error("AOP动态切换数据源异常:", e);
    }

    DataSourceContextHolder.setDatabase(dataSource);

  }

  @After("@annotation(com.linlong.back.core.annotation.DataSource)")
  public void afterSwitch(JoinPoint point) {

    log.info("清空数据源<{}>", DataSourceContextHolder.getDatabase());
    DataSourceContextHolder.clear();
  }

}
  1. DataSourceContextHolder 用于保存数据源信息
@Slf4j
public class DataSourceContextHolder {

  public static final String DEFAULT_DATABASE = "master";

  private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

  public static void setDatabase(String databaseName) {

    log.info("切换到<{}>数据源", databaseName);
    contextHolder.set(databaseName);
  }

  /**
   * 获取数据源
   */
  public static String getDatabase() {
    // 这里也可以直接返回 contextHolder.get(), 在 DynamicDataSource 中指定默认的数据源
    return contextHolder.get() == null ? DEFAULT_DATABASE : contextHolder.get();
  }

  /**
   * 清除数据源
   */
  public static void clear() {
    contextHolder.remove();
  }
}

  1. AbstractRoutingDataSource 抽象路由数据源:决定使用aop中设置数据源
@Slf4j
public class DynamicDataSource extends AbstractRoutingDataSource {

  @Override
  protected Object determineCurrentLookupKey() {
    log.info("确定当前查找的键<{}>", DataSourceContextHolder.getDatabase());
    return DataSourceContextHolder.getDatabase();
  }
}
  1. 数据源设置:设置了默认数据源,所有目标数据源,将此数据源给 SqlSessionFactoryBean 即可
    @Primary
    @Bean(name = DATA_SOURCE)
    public DataSource dataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();

        dynamicDataSource.setDefaultTargetDataSource(masterDataSource());

        Map<Object, Object> targetDataSouces = new HashMap<>();
        targetDataSouces.put("master", masterDataSource());
        targetDataSouces.put("slave", slaveDataSource());

        dynamicDataSource.setTargetDataSources(targetDataSouces);

        return dynamicDataSource;
    }

1. 如何使用?:在 service 中使用注解 @DataScoure("slave")

2. 可能导致的问题?在同一个service中,无法通过 this 调用其他方法(触发aop),事物顺序问题,参考地址:https://blog.csdn.net/dream_broken/article/details/72851329

相关文章

网友评论

      本文标题:SpringBoot MySQL 多数据源配置

      本文链接:https://www.haomeiwen.com/subject/hozfnqtx.html