|
@@ -0,0 +1,40 @@
|
|
|
|
|
+package com.fs.framework.config;
|
|
|
|
|
+
|
|
|
|
|
+import com.fs.framework.datasource.DynamicDataSourceContextHolder;
|
|
|
|
|
+import org.slf4j.MDC;
|
|
|
|
|
+import org.springframework.core.task.TaskDecorator;
|
|
|
|
|
+
|
|
|
|
|
+import java.util.Map;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 异步线程数据源上下文传递装饰器
|
|
|
|
|
+ * 解决 @Async 方法中 ThreadLocal 数据源标识丢失的问题
|
|
|
|
|
+ */
|
|
|
|
|
+public class DataSourceTaskDecorator implements TaskDecorator {
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public Runnable decorate(Runnable runnable) {
|
|
|
|
|
+ // 捕获提交线程的数据源标识
|
|
|
|
|
+ String dataSourceType = DynamicDataSourceContextHolder.getDataSourceType();
|
|
|
|
|
+ // 捕获提交线程的 MDC 上下文
|
|
|
|
|
+ Map<String, String> contextMap = MDC.getCopyOfContextMap();
|
|
|
|
|
+
|
|
|
|
|
+ return () -> {
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 在异步线程中恢复数据源标识
|
|
|
|
|
+ if (dataSourceType != null) {
|
|
|
|
|
+ DynamicDataSourceContextHolder.setDataSourceType(dataSourceType);
|
|
|
|
|
+ }
|
|
|
|
|
+ // 恢复 MDC 上下文
|
|
|
|
|
+ if (contextMap != null) {
|
|
|
|
|
+ MDC.setContextMap(contextMap);
|
|
|
|
|
+ }
|
|
|
|
|
+ runnable.run();
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ // 清理,避免线程复用污染
|
|
|
|
|
+ DynamicDataSourceContextHolder.clearDataSourceType();
|
|
|
|
|
+ MDC.clear();
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+}
|