整理springboot配置多数据源,由AOP实现
先看pom.xml,springboot版本2.1.4
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
再看yml文件
项目结构:
自定义注解 TargetDs:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface TargetDs {
String value() default "";
}
DataSourceConfig.Class:
@Configuration
public class DataSourceConfig {
@Bean(name = "db")
@ConfigurationProperties(prefix = "spring.datasource.db")
public DataSource dataSource1() {
return DataSourceBuilder.create().build();
}
@Bean(name = "db2")
@ConfigurationProperties(prefix = "spring.datasource.db2")
public DataSource dataSource2() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean(name = "dynamicDS1")
public DataSource dataSource() {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
// 默认
dynamicDataSource.setDefaultTargetDataSource(dataSource1());
Map<Object, Object> dsMap = new HashMap();
dsMap.put("db", dataSource1());
dsMap.put("db2", dataSource2());
dynamicDataSource.setTargetDataSources(dsMap);
return dynamicDataSource;
}
/**
* 配置@Transactional注解事物
*/
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}
DataSourceContextHolder.Class
/**
* 默认数据源
*/
public static final String DEFAULT_DS = "db";
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void setDB(String dbType) {
contextHolder.set(dbType);
}
public static String getDB() {
return (contextHolder.get());
}
public static void clearDB() {
contextHolder.remove();
}
DynamicDataSource.Class比较关键的类
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDB();
}
}
DynamicAspect.Class
@Aspect
@Component
public class DynamicAspect {
@Before("@annotation(TargetDs)")
public void before(JoinPoint joinPoint) throws NoSuchMethodException {
Class<?> className = joinPoint.getTarget().getClass();
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
String methodName = methodSignature.getName();
Class[] parameterTypes = methodSignature.getParameterTypes();
Method method = className.getMethod(methodName, parameterTypes);
String dataSource = DataSourceContextHolder.DEFAULT_DS;
if (null != method && method.isAnnotationPresent(TargetDs.class)) {
TargetDs annotation = method.getAnnotation(TargetDs.class);
dataSource = annotation.value();
}
DataSourceContextHolder.setDB(dataSource);
}
@After("@annotation(TargetDs)")
public void afterSwitchDS(JoinPoint point) {
DataSourceContextHolder.clearDB();
}
}
以上就是aop动态切换数据源,默认加载db,加注解可以加载db2,原本想在mapper的接口里去用注解,但是发现有问题,后续研究出来会更新一下。
看一下如何使用:
@Service
public class UserService implements IUserService {
@Autowired
private UserMapper baseDao;
@TargetDs("db2")
public User getUser(){
return baseDao.findUser();
}
}
整体上比较简单,主要就是利用aop。