一、主要依赖

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.4.RELEASE</version><relativePath/>
</parent><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>2.1.4.RELEASE</version>
</dependency>
dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.10</version>
</dependency>

二、yml

# 数据源配置
spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedriverClassName: com.mysql.jdbc.Driverdruid:# 主库数据源master:url: jdbc:mysql://127.0.0.1:3306/master?characterEncoding=UTF-8username: rootpassword: root#树熊数据源slave:enabled : trueurl: jdbc:mysql:127.0.0.1:3306/slave?characterEncoding=UTF-8username: rootpassword: root# 初始连接数initial-size: 10# 最大连接池数量max-active: 100# 最小连接池数量min-idle: 10# 配置获取连接等待超时的时间max-wait: 60000# 打开PSCache,并且指定每个连接上PSCache的大小pool-prepared-statements: truemax-pool-prepared-statement-per-connection-size: 20# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒timeBetweenEvictionRunsMillis: 60000# 配置一个连接在池中最小生存的时间,单位是毫秒min-evictable-idle-time-millis: 300000validation-query: SELECT 1 FROM DUALtest-while-idle: truetest-on-borrow: falsetest-on-return: falsestat-view-servlet:enabled: trueurl-pattern: /druid/*filter:stat:log-slow-sql: trueslow-sql-millis: 1000merge-sql: falsewall:config:multi-statement-allow: true

三、实现
3.1、@DataSource和DataSourceType

/*** 数据源* @author DUCHONG*/
public enum DataSourceType
{/*** 主库*/MASTER,/*** 从库*/SLAVE
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 自定义多数据源切换注解** @author DUCHONG*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource
{/*** 切换数据源名称*/public DataSourceType value() default DataSourceType.MASTER;
}

3.2、DynamicDataSourceContextHolder

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** 数据源切换处理** @author DUCHONG*/
public class DynamicDataSourceContextHolder
{public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class);/*** 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,*  所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。*/private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();/*** 设置数据源的变量*/public static void setDateSourceType(String dsType){log.info("切换到{}数据源", dsType);CONTEXT_HOLDER.set(dsType);}/*** 获得数据源的变量*/public static String getDateSourceType(){return CONTEXT_HOLDER.get();}/*** 清空数据源变量*/public static void clearDateSourceType(){CONTEXT_HOLDER.remove();}
}

3.3、继承AbstractRoutingDataSource

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;import javax.sql.DataSource;
import java.util.Map;/*** 动态数据源** @author DUCHONG*/
public class DynamicDataSource extends AbstractRoutingDataSource
{public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources){super.setDefaultTargetDataSource(defaultTargetDataSource);super.setTargetDataSources(targetDataSources);super.afterPropertiesSet();}@Overrideprotected Object determineCurrentLookupKey(){return DynamicDataSourceContextHolder.getDateSourceType();}
}

3.4、定义切面

import com.starfast.admin.common.annotation.DataSource;
import com.starfast.admin.datasource.DynamicDataSourceContextHolder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;/*** 多数据源处理* @author DUCHONG*/
@Aspect
@Order(1)
@Component
public class DataSourceAspect
{protected Logger logger = LoggerFactory.getLogger(getClass());@Pointcut("@annotation(com.duchong.common.annotation.DataSource)")public void dsPointCut(){}@Around("dsPointCut()")public Object around(ProceedingJoinPoint point) throws Throwable{MethodSignature signature = (MethodSignature) point.getSignature();Method method = signature.getMethod();DataSource dataSource = method.getAnnotation(DataSource.class);if (null!=dataSource){DynamicDataSourceContextHolder.setDateSourceType(dataSource.value().name());}try{return point.proceed();}finally{// 销毁数据源 在执行方法之后DynamicDataSourceContextHolder.clearDateSourceType();}}
}

3.5、@Configuration

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.starfast.admin.common.enums.DataSourceType;
import com.starfast.admin.datasource.DynamicDataSource;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;/*** druid 配置多数据源** @author DUCHONG*/
@Configuration
public class DruidConfig
{@Bean@ConfigurationProperties("spring.datasource.druid.master")public DataSource masterDataSource(){return DruidDataSourceBuilder.create().build();}@Bean@ConfigurationProperties("spring.datasource.druid.slave")@ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true")public DataSource slaveDataSource(){return DruidDataSourceBuilder.create().build();}@Bean(name = "dynamicDataSource")@Primarypublic DynamicDataSource dataSource(){Map<Object, Object> targetDataSources = new HashMap<>();targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource());targetDataSources.put(DataSourceType.SLAVE.name(), slaveDataSource());return new DynamicDataSource(masterDataSource(), targetDataSources);}
}

3.6、使用
需要切换数据源的方法上加

@DataSource(value = DataSourceType.SLAVE)

springboot项目自定义注解实现的多数据源切换--亲测有效相关推荐

  1. SpringBoot项目优化和Jvm调优(楼主亲测,真实有效)

    今日推荐Spring新版本抛弃JVM,可独立部署,网友:要自立门户???国内大神成功给手机装上了 Win11,代码已开源!Fluent Mybatis 牛逼!Nginx 常用配置清单这玩意比Threa ...

  2. Flowable springboot项目自定义中文字体

    Flowable springboot项目自定义中文字体 摘要:在flowable框架中,当我们想要集成springboot框架的时候,可能要设置中文字体,flowable6.4之前的版本因为没有可以 ...

  3. springboot+aop+自定义注解,打造通用的全局异常处理和参数校验切面(通用版)

    springboot+aop+自定义注解,打造通用的全局异常处理和参数校验切面(通用版) 参考文章: (1)springboot+aop+自定义注解,打造通用的全局异常处理和参数校验切面(通用版) ( ...

  4. 升级node,老的项目启动不了的解决方法(亲测有效)

    升级node,老的项目启动不了的解决方法(亲测有效) 参考文章: (1)升级node,老的项目启动不了的解决方法(亲测有效) (2)https://www.cnblogs.com/chenzhengy ...

  5. 【SpringBoot】66、SpringBoot使用自定义注解实现返回数据脱敏操作

    在实际项目中,对于敏感数据的保护显得十分重要,数据脱敏又称数据去隐私化或数据变形,是在给定的规则.策略下对敏感数据进行变换.修改的技术机制,能够在很大程度上解决敏感数据在非可信环境中使用的问题. 本文 ...

  6. springBoot 项目自定义命名application.properties配置文件名称

    最近因项目原因,需要将springboot项目的properties文件改为自定义名称,在查看一些资料后最终解决,特记录一下! 参考资料:https://docs.spring.io/spring-b ...

  7. springboot整合自定义注解Log过程(借鉴ruoyi的common-log)整理思路

    整合过程 maven依赖 新建自定义注解类 Log 自定义切面 Aspect中使用到的工具类 enums类 service层 日志实体类 后记 maven依赖 可能不全这个依赖,如果实在找不到你在留言 ...

  8. SpringBoot fastjson自定义注解时间转时间戳

    spirngboot 中有时候需要将时间类型比如 LocalDateTime.Date 返回给前端,但是一般会和前端约定好转换为时间戳给前端.正常来说使用全局配置,统一转换,比如重写一个DateCon ...

  9. SpringBoot项目-自定义默认网页图标

    在不修改SpringBoot项目图标的时候,往往默认是一个小树叶图标 在有些时候需要修改图标,不想用它的默认图标,下面是我自己修改的步骤,亲测可行 首先,把SpringBoot项目默认访问图片设置为f ...

  10. Spring-基于Spring使用自定义注解及Aspect实现数据库切换

    文章目录 实现思路 示例 步骤一 新建Maven工程 步骤二 继承AbstractRoutingDataSource并重写determineCurrentLookupKey方法获取特定数据源 步骤三 ...

最新文章

  1. [NOI2005]聪聪与可可(期望dp)
  2. stm32编码器正反转计数程序_编码器接线方法你会吗?
  3. ssha java接口_java – 从Spring在LDAP中设置SSHA密码
  4. 同步类的基础AbstractQueuedSynchronizer(AQS)
  5. Android全局窗口模糊,javascript – 窗口焦点和模糊事件在Android浏览器上无法正常工作...
  6. (07)Verilog HDL组合逻辑:assign
  7. python 人脸检测_借助摄像头在Python中实现人脸检测
  8. jsp中头的导入两种方式区别
  9. 高效办公之远程电脑控制:再也不用带着厚重笔记本
  10. c语言1%3等于多少,%取余语句1%3等于多少的作用
  11. Flink 实践教程-进阶(11):SQL 关联:Regular Join
  12. svn如何修改443端口
  13. 2011年的暑假(大一的暑假——还算充实)
  14. PostgreSQL行级安全策略RLS和数据加密
  15. eplan支持mysql_EPLAN软件平台系统和电脑要求
  16. C++跳出for循环
  17. 波音 737 连续坠毁,AI 要背锅?
  18. C/C++ 报数游戏
  19. 阿里云呼叫中心发布,为企业提供更灵活可靠的热线服务
  20. 京东三级列表页持续架构优化

热门文章

  1. VS模板导入导出 提高工作效率
  2. List的Sort自定义排序实例
  3. laravel windows、linux下软连接创建
  4. Azure Services Bus(服务总线)中的工作流(workflow)
  5. css3实现浮动元素垂直水平居中
  6. 新物联网时代的整合战略
  7. 数据仓库搭建——Inmon与Kimball
  8. 冲突域和CSMA/CD
  9. JS iframe 跨域
  10. Udp通信 暑期学习笔记(三)