日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

SpringBoot AOP+注解方式實現多數據源切換可能遇到的問題

作者:騎個小蝸牛 更新時間: 2023-07-10 編程語言

文章目錄

  • AOP+注解方式實現多數據源原理
  • 可能遇到的問題
    • 情景1:指定數據源的請求中發生報錯
    • 情景2:指定數據源的請求中使用新的線程


AOP+注解方式實現多數據源原理

通過ThreadLocal的線程隔離性將設線程與數據源ID進行綁定:

  • 若不設置則使用默認數據源
  • 若設置則使用該數據源ID對應的數據源(注意:使用完后需要清除該數據源ID)

可能遇到的問題

情景1:指定數據源的請求中發生報錯

問題描述:指定數據源的請求中發生報錯,后面未指定數據源的請求卻使用了該指定數據源(應該使用默認數據源)。

代碼:

@Slf4j
@Aspect
@Order(-2)
@Component
public class DataSourceAspect {

    @Pointcut("@annotation(com.joker.datasource.aopannotation.DataSource) || @within(com.joker.datasource.aopannotation.DataSource)")
    public void run(){

    }

    @Around("run()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        // 方法上獲取
        // AnnotatedElementUtils.hasAnnotation()
        DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class);
        if (Objects.isNull(dataSource)) {
            // 類上獲取
            dataSource =  AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class);
        }
        // 設置數據源
        DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());
        Object obj = point.proceed();
        // 清除數據源
        DynamicDataSourceContextHolder.clearDataSourceType();
        return obj;
    }
}

問題分析:

  1. 指定數據源的請求中發生報錯,導致清除數據源ID未執行,當前線程thread1仍然綁定了該數據源;
  2. 由于接口請求使用的線程是通過線程池來管理的,后續該線程thread1可能會繼續分配給其它請求使用
  3. 如果后續請求使用了該線程thread1且未指定數據源,使用的仍然是前面綁定的數據源,導致使用錯數據源(原本應該使用默認數據源)
  4. 但如果后續請求使用了該線程thread1但指定了數據源,則不會有問題

情景2:指定數據源的請求中使用新的線程

問題描述:指定數據源的請求中使用新的線程,導致指定數據源無效,使用的是默認數據源。

問題分析:因為數據源是和線程綁定的,即使在當前線程綁定了指定數據源,但如果在請求中使用了新的線程,新線程是沒有綁定數據源的(默認使用默認數據源)。使用新線程的一下場景:

  1. 使用了new Thread()創建的新線程,在新線程中使用數據源
  2. 使用了線程池,通過線程池中的線程來使用數據源
  3. 使用了Java8中list.parallelStream()來并行處理(多線程處理),處理過程中使用數據

原文鏈接:https://blog.csdn.net/JokerLJG/article/details/131406803

  • 上一篇:沒有了
  • 下一篇:沒有了
欄目分類
最近更新