有个需求需要通过开关控制需要访问的数据源,此处参考DS多数据源,采用注解加aop切面实现此功能。
配置文件开关:
slave-config:mainSlaveSwitch: true
配置开关类:
@Component
@RefreshScope
@Data
@ConfigurationProperties("slave-config")
public class SlaveConfig {private boolean mainSlaveSwitch=false;
}
多数据源配置:
datasource:dynamic:primary: masterdatasource:master:url: jdbc:mysql://xxxx:3306/order?useUnicode=true&characterEncoding=utf-8&useSSL=falseusername: gac_travel_devpassword: gac@6666driverClassName: com.mysql.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSourcedruid:initialSize: 10maxActive: 20minIdle: 5maxWait: 1000minEvictableIdleTimeMillis: 300000useGlobalDataSourceStat: truetimeBetweenEvictionRunsMillis: 60000validationQuery: select 'x'testOnBorrow: truetestOnReturn: truetestWhileIdle: trueslave:url: jdbc:mysql://xxxx:3306/order/gac_order?useUnicode=true&characterEncoding=utf-8&useSSL=falseusername: gac_dev_readpassword: gac@6666type: com.alibaba.druid.pool.DruidDataSourcedruid:initialSize: 10maxActive: 20minIdle: 5maxWait: 1000minEvictableIdleTimeMillis: 300000useGlobalDataSourceStat: truetimeBetweenEvictionRunsMillis: 60000validationQuery: select 'x'testOnBorrow: truetestOnReturn: truetestWhileIdle: truemainslave:url: jdbc:mysql://xxxx:3306/order/gac_order?useUnicode=true&characterEncoding=utf-8&useSSL=falseusername: gac_travel_testpassword: gac@6666type: com.alibaba.druid.pool.DruidDataSourcedruid:initialSize: 10maxActive: 20minIdle: 5maxWait: 1000minEvictableIdleTimeMillis: 300000useGlobalDataSourceStat: truetimeBetweenEvictionRunsMillis: 60000validationQuery: select 'x'testOnBorrow: truetestOnReturn: truetestWhileIdle: true
多数据源静态类(不是必须的):
public interface DBTypeConst {/*** 主库*/String MASTER = "master";/*** 主库的从库*/String MAIN_SLAVE = "mainslave";/*** 从库*/String SLAVE = "slave";}
多数据源注解:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DynamicDataSource {
}
AOP切面:
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;@Aspect
@Component
@Slf4j
public class DynamicDataSourceAspect {@AutowiredSlaveConfig slaveConfig;@Around("@annotation(dynamicDataSource)")public Object switchDataSource(ProceedingJoinPoint joinPoint, DynamicDataSource dynamicDataSource) throws Throwable {if(slaveConfig.isMainSlaveSwitch()){log.info("DynamicDataSourceAspect:{}",DBTypeConst.MAIN_SLAVE);DynamicDataSourceContextHolder.push(DBTypeConst.MAIN_SLAVE);}else{log.info("DynamicDataSourceAspect:{}",DBTypeConst.SLAVE);DynamicDataSourceContextHolder.push(DBTypeConst.SLAVE);}try {return joinPoint.proceed();} finally {DynamicDataSourceContextHolder.clear();}}
}
此处使用时要多测试防止异常