自定义注解+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要配置数据源链接
不然就报这个错:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)