目录结构:

 

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.springframework.core.annotation.Order;

import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

import java.util.Objects;

/**

* @Description 动态数据源AOP切换

* @Author WangKun

* @Date 2023/4/4 11:23

* @Version

*/

@Aspect

@Component

@Order(1) //配置加载顺序

public class DataSourceAspect {

@Pointcut("@annotation(DB类的路径)")

public void doPointCut() {

}

/**

* @param point

* @Description 切点

* @Throws

* @Return java.lang.Object

* @Date 2023-04-04 11:24:11

* @Author WangKun

*/

@Around("doPointCut()")

public Object around(ProceedingJoinPoint point) throws Throwable {

DB dataSource = getDataSource(point);

if (!Objects.isNull(dataSource)) {

DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());

}

try {

return point.proceed();

} finally {

// 在执行方法之后 销毁数据源

DynamicDataSourceContextHolder.clearDataSourceType();

}

}

/**

* @param point

* @Description 获取@DB注解

* @Throws

* @Return com.harmonywisdom.common.system.annotation.DB

* @Date 2023-04-04 11:25:03

* @Author WangKun

*/

public DB getDataSource(ProceedingJoinPoint point) {

//获得当前访问的class

Class className = point.getTarget().getClass();

// 判断是否存在@DateBase注解

if (className.isAnnotationPresent(DB.class)) {

//获取注解

return className.getAnnotation(DB.class);

}

Method method = ((MethodSignature) point.getSignature()).getMethod();

return method.getAnnotation(DB.class);

}

}

import java.lang.annotation.*;

/**

* @Description 注解方式切换 在**ServiceImpl中的方法上面使用此注解,默认位主数据库可不写, @DB(DataSourceType.DB2)

* @Author WangKun

* @Date 2023/4/4 14:23

* @Version

*/

@Target({ ElementType.METHOD, ElementType.TYPE })

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inherited

public @interface DB

{

/**

* 切换数据源名称

*/

DataSourceType value() default DataSourceType.DB1;

}

\

import com.zaxxer.hikari.HikariDataSource;

import org.springframework.beans.factory.annotation.Qualifier;

import org.springframework.boot.context.properties.ConfigurationProperties;

import org.springframework.boot.jdbc.DataSourceBuilder;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.context.annotation.Primary;

import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

import java.util.HashMap;

import java.util.Map;

/**

* @Description Hikari多数据源配置

* @Author WangKun

* @Date 2023/4/4 15:00

* @Version

*/

@Configuration

public class HikariConfig {

@Bean(name = "dataSourceDb1")

@ConfigurationProperties("spring.datasource.db1")

public DataSource dataSourceDb1(HikariProperties properties) {

HikariDataSource dataSource = DataSourceBuilder.create().type(HikariDataSource.class).build();

return properties.dataSource(dataSource);

}

@Bean(name = "dataSourceDb2")

@ConfigurationProperties("spring.datasource.db2")

public DataSource dataSourceDb2(HikariProperties properties) {

HikariDataSource dataSource = DataSourceBuilder.create().type(HikariDataSource.class).build();

return properties.dataSource(dataSource);

}

@Bean(name = "dataSourceDb3")

@ConfigurationProperties("spring.datasource.db3")

public DataSource dataSourceDb3(HikariProperties properties) {

HikariDataSource dataSource = DataSourceBuilder.create().type(HikariDataSource.class).build();

return properties.dataSource(dataSource);

}

@Bean(name = "dataSourceDb4")

@ConfigurationProperties("spring.datasource.db4")

public DataSource dataSourceDb4(HikariProperties properties) {

HikariDataSource dataSource = DataSourceBuilder.create().type(HikariDataSource.class).build();

return properties.dataSource(dataSource);

}

@Primary

@Bean(name = "dynamicDataSource")

public DynamicDataSource dataSource(DataSource dataSourceDb1, DataSource dataSourceDb2, DataSource dataSourceDb3, DataSource dataSourceDb4) {

Map targetDataSources = new HashMap<>();

targetDataSources.put(DataSourceType.DB1.name(), dataSourceDb1);

targetDataSources.put(DataSourceType.DB2.name(), dataSourceDb2);

targetDataSources.put(DataSourceType.DB3.name(), dataSourceDb3);

targetDataSources.put(DataSourceType.DB4.name(), dataSourceDb4);

return new DynamicDataSource(dataSourceDb1, targetDataSources);

}

/**

* @param dataSource

* @Description 创建事务

* @Throws

* @Return org.springframework.jdbc.datasource.DataSourceTransactionManager

* @Date 2023-04-10 15:26:50

* @Author WangKun

*/

@Primary

@Bean(name = "transactionManager")

public DataSourceTransactionManager transactionManager(@Qualifier("dynamicDataSource") DataSource dataSource) {

return new DataSourceTransactionManager(dataSource);

}

}

import com.zaxxer.hikari.HikariDataSource;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Configuration;

/**

* @Description Hikari连接池设置

* @Author WangKun

* @Date 2023/4/4 15:05

* @Version

*/

@Configuration

public class HikariProperties {

@Value("${spring.datasource.hikari.minimumIdle}")

private int minIdle;

@Value("${spring.datasource.hikari.maximumPoolSize}")

private int maxPoolSize;

@Value("${spring.datasource.hikari.idleTimeout}")

private int idleTimeout;

@Value("${spring.datasource.hikari.maxLifetime}")

private int maxLifetime;

@Value("${spring.datasource.hikari.connectionTimeout}")

private int connectionTimeout;

public HikariDataSource dataSource(HikariDataSource dataSource) {

//配置Hikari连接池

dataSource.setConnectionTimeout(connectionTimeout);//连接超时时间设置

dataSource.setIdleTimeout(idleTimeout);//连接空闲生命周期设置

dataSource.setMaximumPoolSize(maxPoolSize);//连接池允许的最大连接数量

dataSource.setMaxLifetime(maxLifetime);//检查空余连接优化连接池设置时间,单位毫秒

dataSource.setMinimumIdle(minIdle);//连接池保持最小空余连接数量

return dataSource;

}

}

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import javax.sql.DataSource;

import java.util.Map;

/**

* @Description 自定义动态数据源

* @Author WangKun

* @Date 2023/4/4 15:05

* @Version

*/

public class DynamicDataSource extends AbstractRoutingDataSource {

public DynamicDataSource(DataSource defaultTargetDataSource, Map targetDataSources) {

super.setDefaultTargetDataSource(defaultTargetDataSource);

super.setTargetDataSources(targetDataSources);

super.afterPropertiesSet();

}

@Override

protected Object determineCurrentLookupKey() {

return DynamicDataSourceContextHolder.getDataSourceType();

}

}

import lombok.extern.slf4j.Slf4j;

/**

* @Description 动态数据源切换处理

* @Author WangKun

* @Date 2023/4/4 11:30

* @Version

*/

@Slf4j

public class DynamicDataSourceContextHolder {

/**

* 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量,

* 所以每一个线程都可以独立地改变自己,而不会影响其它线程。

*/

private static final ThreadLocal CONTEXT_HOLDER = new ThreadLocal<>();

/**

* @param dsType

* @Description 设置数据源的变量

* @Throws

* @Return void

* @Date 2023-04-04 11:30:21

* @Author WangKun

*/

public static void setDataSourceType(String dsType) {

CONTEXT_HOLDER.set(dsType);

log.info("连接到{}数据源", dsType);

}

/**

* @param

* @Description 获得数据源的变量

* @Throws

* @Return java.lang.String

* @Date 2023-04-04 11:30:45

* @Author WangKun

*/

public static String getDataSourceType() {

return CONTEXT_HOLDER.get();

}

/**

* @param

* @Description 清空数据源变量

* @Throws

* @Return void

* @Date 2023-04-04 11:30:51

* @Author WangKun

*/

public static void clearDataSourceType() {

CONTEXT_HOLDER.remove();

}

}

/**

* @Description 数据源枚举

* @Author WangKun

* @Date 2023/4/4 11:23

* @Version

*/

public enum DataSourceType {

/**数据源1 */

DB1,

/**数据源2 */

DB2,

/**数据源3 */

DB3,

/**数据源4 */

DB4

}

调用:

 

 

 

好文链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: