1.application.yml配置文件
例:
// A数据源
A:
driverClassName: com.ibMm.db2s.jcc.DB2Drivers
jdbc-url: jdbc:db2s://10.666.66.666:50000/tkrmk
username: AAAAuserss
password: 123456789
// B数据源
B: 此处省略...
2.自定义注解
@Documented
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DBSource{
// 默认ccam数据源
String value() default "A";
}
3.创建DataSourceContextHolder类
public class DataSourceContextHolder{
static final String DEFAULT_DATABASE = "A";
private static final ThreadLocal<String> CONTEXTHOLDER = new ThreadLocal<>();
// 获取数据源
public static String getDataBase(){
// 线程源码中的方法 获取当前线程注解中的value值
return CONTEXTHOLDER.get();
}
// 设置数据源
setDataBase方法 同上
// 清空数据源
removeDataBase方法 同上
}
4.创建切面类 扫描该注解
@Aspect
@Component
public class DynamicDataSourceAspect{
// 切点(所有的Dao层)
@Pointcut(value="bean(*Dao)")
public void daoPointcut(){}
// 切点位置 所有@DBSource注解
@Pointcut(value="@annotation(DBSource)")
public voic dsPointcut(){}
// 在选中的切点之前执行
@Before(value="daoPointcut() && dsPointcut()")
public void beforeDataSource(){
// 默认注入ccam数据源
String dataSource = DataSourceContextHolder.DEFAULT_DATABASE;
try{
// 获取当前线程中的方法名称
MethodSignature signature = joinPoint.getSignature();
Method method = signature.getMethod();
// 自定义注解使用的是RUNTIME可以通过反射获取 判断是否是该注解
if(method.isAnnotationPresent(DBSource.class)){
// 获取注解信息
DBSource annotation = method.getAnnotation(DBSource.class);
dataSource = annotation.value();
}
}catch(Exception e){
// 不建议打印
e.printStackTrace();
}
// 切换数据源(只在当前线程生效)
DataSourceContextHolder.setDataBase(dataSource);
}
// 后置清空数据源信息
@After(value = "daoPointcut() && dsPointcut()")
public void afterDataSource(JoinPoint joinPoint){
DataSourceContextHolder.removeDataBase(dataSource);
}
}
5.继承AbstractRoutingDataSource类实现数据库热切换
public class DynamicDataSource extends AbstractRoutingDataSource{
@Override
protected Object datermineCurrentLookupKey(){
// return注入到当前线程中的数据源
return DataSourceContextHolder.getDatabase();
}
}