项目主要结构如下:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface DataSourceSwitch {
DBTypeEnum value() default DBTypeEnum.db1;
}
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
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.util.Objects;
@Component
@Aspect
@Order(-100)
@Slf4j
public class DataSourceSwitchAspect {
@Pointcut("execution(* com.*.*.*.sp.*.*.service..*.*(..))")
private void db1Aspect() {
}
@Pointcut("execution(* com.*.*.*.sp.*.*.service..*.*(..))")
private void db2Aspect() {
}
@Before("db1Aspect()")
public void db1(JoinPoint joinPoint) {
log.info("切换到db1Source 数据源...");
setDataSource(joinPoint, DBTypeEnum.db1);
}
@Before("db2Aspect()" )
public void db2 (JoinPoint joinPoint) {
log.info("切换到db2Source 数据源...");
setDataSource(joinPoint, DBTypeEnum.db2);
}
/**
* 添加注解方式,如果有注解优先注解,没有则按传过来的数据源配置
* @param joinPoint
* @param dbTypeEnum
*/
private void setDataSource(JoinPoint joinPoint, DBTypeEnum dbTypeEnum) {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
DataSourceSwitch dataSourceSwitch = methodSignature.getMethod().getAnnotation(DataSourceSwitch.class);
if (Objects.isNull(dataSourceSwitch) || Objects.isNull(dataSourceSwitch.value())) {
DBContextHolder.setDBType(dbTypeEnum);
}else{
log.info("根据注解来切换数据源,注解值为:"+dataSourceSwitch.value());
switch (dataSourceSwitch.value().getValue()) {
case "db1":
DBContextHolder.setDBType(DBTypeEnum.db1);
break;
case "db2":
DBContextHolder.setDBType(DBTypeEnum.db2);
break;
default:
DBContextHolder.setDBType(dbTypeEnum);
}
}
}
}
public class DBContextHolder {
private static final ThreadLocal contextHolder = new ThreadLocal<>();
/**
* 设置数据源
* @param dbTypeEnum
*/
public static void setDBType(DBTypeEnum dbTypeEnum) {
contextHolder.set(dbTypeEnum.getValue());
}
/**
* 取得当前数据源
* @return
*/
public static String getDBType() {
return (String) contextHolder.get();
}
/**
* 清除上下文数据
*/
public static void clearType() {
contextHolder.remove();
}
}
public enum DBTypeEnum {
db1("db1"),
db2("db1");
private String value;
DBTypeEnum(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DBContextHolder.getDBType();
}
}
serviceimpl层
@DataSourceSwitch(DBTypeEnum.db1)
@Override
public dto find (String userid) {
return testDao. find ( userid) ;
}
<!-- 动态数据源,根据service接口上的注解来决定取哪个数据源 -->
<bean id="dataSource" class="com.*.*.*.sp.dataSource.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="db1" value-ref="db1"/>
<entry key="db2" value-ref="db2"/>
</map>
</property>
<!--默认用主库 -->
<property name="defaultTargetDataSource" ref="db1"/>
</bean>