目標:日志與生產業務使用不同資料源,Service 層透明切換。
AbstractRoutingDataSource:public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DatabaseContextHolder.getCustomerType();
}
}ThreadLocal 存儲當前資料源標識:public class DatabaseContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void setCustomerType(String type) { contextHolder.set(type); }
public static String getCustomerType() { return contextHolder.get(); }
public static void clearCustomerType() { contextHolder.remove(); }
}@Aspect
@Component
public class DataSourceInterceptor {
@Before("execution(* com.service.log.*.*(..))")
public void setLogDataSource() { DatabaseContextHolder.setCustomerType("dataSourceTwo"); }
@Before("execution(* com.service.prod.*.*(..))")
public void setProdDataSource() { DatabaseContextHolder.setCustomerType("dataSourceOne"); }
@After("execution(* com.service.*.*.*(..))")
public void clear() { DatabaseContextHolder.clearCustomerType(); }
}DataSource Bean,注入 DynamicDataSource 作為默認 dataSource。若在同一事務中跨資料源操作,需使用 JTA (Atomikos/Bitronix) 或避免跨庫事務。本方案適用於「單一事務內單一資料源」場景。
在 Service 方法入口打印 DatabaseContextHolder.getCustomerType() 確認切換生效。