自定义注解+aop实现分库

首先先配置这几个类和注解

DataSource注解,用来辨别方法上是否有此注解,有的话就切库
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
    DataSourceType value() default DataSourceType.XIAOKUN;
}
DataSourceAspect切面类,用于判断方法上是否存在DataSource注解
复制代码
@Aspect
@Order(1)
@Component
public class DataSourceAspect {

    @Pointcut("@annotation(com.example.demo.mult.DataSource)")
    public void dsPointCut(){

    }

    @Around("dsPointCut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint){
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        Method method = signature.getMethod();
        DataSource dataSource = method.getAnnotation(DataSource.class);
        if (dataSource != null){
            DynamicDataSourceContextHolder.setContextHolder(dataSource.value().name());
        }
        try {
            return proceedingJoinPoint.proceed();
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }finally {
            DynamicDataSourceContextHolder.cleanDataSourceType();
        }
    }

}
复制代码
DataSourceConfig数据源配置类
复制代码
@Configuration
public class DataSourceConfig {

    @Bean
    @ConfigurationProperties("spring.datasource.xiaokun")
    public DataSource getXiaokun() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties("spring.datasource.yk")
    public DataSource getYK() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "dataSource")
    @Primary
    public DynamicDataSource dataSource(DataSource getXiaokun, DataSource getYK) {
        HashMap<Object, Object> targetDataSource = new HashMap<>();
        targetDataSource.put(DataSourceType.XIAOKUN.name(), getXiaokun);
        targetDataSource.put(DataSourceType.YK.name(), getYK);
        return new DynamicDataSource(getXiaokun,targetDataSource);
    }

}
复制代码
DataSourceType数据源类型枚举
public enum DataSourceType {
    XIAOKUN,
    YK
}
DynamicDataSource动态数据源类
复制代码
public class DynamicDataSource extends AbstractRoutingDataSource {

    public DynamicDataSource(DataSource defaultDataSource, Map<Object, Object> targetDataSource) {
        super.setDefaultTargetDataSource(defaultDataSource);
        super.setTargetDataSources(targetDataSource);
        super.afterPropertiesSet();
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceContextHolder.getDataSourceType();
    }
}
复制代码
DynamicDataSourceContextHolder
复制代码
public class DynamicDataSourceContextHolder {
    private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();

    public static void setContextHolder(String dataSourceType) {
        System.out.println("切换到数据源===========" + dataSourceType);
        CONTEXT_HOLDER.set(dataSourceType);
    }

    public static String getDataSourceType(){
        return CONTEXT_HOLDER.get();
    }

    public static void cleanDataSourceType(){
        CONTEXT_HOLDER.remove();
    }
}
复制代码

 

 

yml文件配置数据源链接

复制代码
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    xiaokun:
      username: root_max
      password: xxx
      jdbc-url: jdbc:mysql://xxx:3306/xiaokun?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false
      driver-class-name: com.mysql.jdbc.Driver
    yk:
      username: root_max
      password: xxx
      jdbc-url: jdbc:mysql://xxx:3306/yk?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false
      driver-class-name: com.mysql.jdbc.Driver
    druid:
      initial-size: 10
      max-active: 100
      min-idle: 10
      max-wait: 60000
      pool-prepared-statements: true
      max-pool-prepared-statement-per-connection-size: 20
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
复制代码

  

 

测试:

 

 

 

报错总结:

1、启动类要排除掉默认阿里的数据源

 

不然报循环依赖的错:

 

 

 2、yml要配置数据源链接

不然就报这个错:

 

posted @   古家杰  阅读(57)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示