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

學(xué)無先后,達(dá)者為師

網(wǎng)站首頁 編程語言 正文

SpringBoot AOP+注解方式實(shí)現(xiàn)多數(shù)據(jù)源切換可能遇到的問題

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

文章目錄

  • AOP+注解方式實(shí)現(xiàn)多數(shù)據(jù)源原理
  • 可能遇到的問題
    • 情景1:指定數(shù)據(jù)源的請求中發(fā)生報(bào)錯
    • 情景2:指定數(shù)據(jù)源的請求中使用新的線程


AOP+注解方式實(shí)現(xiàn)多數(shù)據(jù)源原理

通過ThreadLocal的線程隔離性將設(shè)線程與數(shù)據(jù)源ID進(jìn)行綁定:

  • 若不設(shè)置則使用默認(rèn)數(shù)據(jù)源
  • 若設(shè)置則使用該數(shù)據(jù)源ID對應(yīng)的數(shù)據(jù)源(注意:使用完后需要清除該數(shù)據(jù)源ID)

可能遇到的問題

情景1:指定數(shù)據(jù)源的請求中發(fā)生報(bào)錯

問題描述:指定數(shù)據(jù)源的請求中發(fā)生報(bào)錯,后面未指定數(shù)據(jù)源的請求卻使用了該指定數(shù)據(jù)源(應(yīng)該使用默認(rèn)數(shù)據(jù)源)。

代碼:

@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);
        }
        // 設(shè)置數(shù)據(jù)源
        DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());
        Object obj = point.proceed();
        // 清除數(shù)據(jù)源
        DynamicDataSourceContextHolder.clearDataSourceType();
        return obj;
    }
}

問題分析:

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

情景2:指定數(shù)據(jù)源的請求中使用新的線程

問題描述:指定數(shù)據(jù)源的請求中使用新的線程,導(dǎo)致指定數(shù)據(jù)源無效,使用的是默認(rèn)數(shù)據(jù)源。

問題分析:因?yàn)閿?shù)據(jù)源是和線程綁定的,即使在當(dāng)前線程綁定了指定數(shù)據(jù)源,但如果在請求中使用了新的線程,新線程是沒有綁定數(shù)據(jù)源的(默認(rèn)使用默認(rèn)數(shù)據(jù)源)。使用新線程的一下場景:

  1. 使用了new Thread()創(chuàng)建的新線程,在新線程中使用數(shù)據(jù)源
  2. 使用了線程池,通過線程池中的線程來使用數(shù)據(jù)源
  3. 使用了Java8中l(wèi)ist.parallelStream()來并行處理(多線程處理),處理過程中使用數(shù)據(jù)

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

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