mybatis多数据源切换-AOP实现

mybatis多数据源切换--AOP实现

  • 方案
  • 代码
    • 1.配置相关
      • pom.xml
      • yml文件
      • yml对应配置类
      • 数据源配置类
      • 数据源切换类
      • 动态数据源类(重点)
    • 2.aop
      • 注解
      • 切面

方案

  1. AOP+注解:适用于方法级的数据源动态切换
  2. 分包法(生成多个SqlSessionFactory,分别指定不同的mapper包)
    这里我先介绍常用的方式:AOP+注解

代码

1.配置相关

pom.xml

<dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-webartifactId>dependency><dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-aopartifactId>dependency><dependency><groupId>com.alibabagroupId><artifactId>druid-spring-boot-starterartifactId><version>1.2.6version>dependency><dependency><groupId>org.mybatis.spring.bootgroupId><artifactId>mybatis-spring-boot-starterartifactId><version>2.1.4version>dependency><dependency><groupId>mysqlgroupId><artifactId>mysql-connector-javaartifactId><version>8.0.24version>dependency><dependency><groupId>org.projectlombokgroupId><artifactId>lombokartifactId><optional>trueoptional>dependency>

yml文件

mybatis:type-aliases-package: com.jenkins.domainmapper-locations: classpath*:/mapper/*.xmlspring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedbs:db1:url: jdbc:mysql://ip:3306/db1?useSSL=false&serverTimezone=UTCusername: rootpassword: admindriver-class-name: com.mysql.cj.jdbc.Driverdb2:url: jdbc:mysql://ip:3306/db2?useSSL=false&serverTimezone=UTCusername: rootpassword: admindriver-class-name: com.mysql.cj.jdbc.Driver

yml对应配置类

@Data
@Configuration
@ConfigurationProperties(prefix = "spring.datasource")
public class DbConfig {private Map<String, DruidDataSource> dbs;
}

数据源配置类

@Configuration
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class DynamicDataSourceConfig {private final DbConfig dbConfig;@Bean("dynamicDataSource")public DynamicDataSource dynamicDataSource() {Map<Object, Object> dataSourceMap = new HashMap<>();dbConfig.getDbs().forEach(dataSourceMap::put);DynamicDataSource dynamicDataSource = new DynamicDataSource();dynamicDataSource.setTargetDataSources(dataSourceMap);dynamicDataSource.setDefaultTargetDataSource(dbConfig.getDbs().get("db1"));return dynamicDataSource;}}

数据源切换类

public class DynamicDataSourceContextHolder {public static final String DS1_KEY = "db1";public static final String DS2_KEY = "db2";/*** 动态数据源名称上下文,每个线程互不影响*/private static final ThreadLocal<String> DATASOURCE_CONTEXT_KEY = new ThreadLocal<>();/*** 设置/切换数据源*/public static void setContextKey(String key) {DATASOURCE_CONTEXT_KEY.set(key);}/*** 获取数据源名称*/public static String getContextKey() {String key = DATASOURCE_CONTEXT_KEY.get();return key == null ? DS1_KEY : key;}/*** 删除当前数据源名称*/public static void removeContextKey() {DATASOURCE_CONTEXT_KEY.remove();}
}

动态数据源类(重点)

public class DynamicDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {return DynamicDataSourceContextHolder.getContextKey();}
}

2.aop

注解

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {String value();
}

切面

@Aspect
@Component
public class DataSourceAspect {@Pointcut("@annotation(com.hui.annotations.DataSource)")public void pointCut() {}@Around("pointCut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {String dsKey = getDSAnnotation(joinPoint).value();//切换数据源DynamicDataSourceContextHolder.setContextKey(dsKey);try {return joinPoint.proceed();} finally {DynamicDataSourceContextHolder.removeContextKey();}}/*** 根据类或方法获取数据源注解*/private DataSource getDSAnnotation(ProceedingJoinPoint joinPoint) {//获取被代理的对象Class<?> targetClass = joinPoint.getTarget().getClass();DataSource dsAnnotation = targetClass.getAnnotation(DataSource.class);// 先判断类上是否有该注解,再判断方法上是否有注解if (Optional.ofNullable(dsAnnotation).isPresent()) {return dsAnnotation;} else {//获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();return methodSignature.getMethod().getAnnotation(DataSource.class);}}
}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部