亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot利用自定義注解實(shí)現(xiàn)多數(shù)據(jù)源

 更新時(shí)間:2022年10月13日 08:33:25   作者:look-word  
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何利用自定義注解實(shí)現(xiàn)多數(shù)據(jù)源效果,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以了解一下

前置學(xué)習(xí)

需要了解 注解、Aop、SpringBoot整合Mybatis的使用。

數(shù)據(jù)準(zhǔn)備

基礎(chǔ)項(xiàng)目代碼:https://gitee.com/J_look/spring-boot-all-demo

數(shù)據(jù)庫SQL 項(xiàng)目中有提供,修改基本信息即可

行動(dòng)起來

添加依賴

利用 AOP 可以實(shí)現(xiàn)對某些代碼的解耦,不需要硬編碼編寫。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

開啟AOP支持

也可以像圖中一樣,也開啟事務(wù)管理器,下文會(huì)演示事務(wù)失效的問題。

定義枚舉

這里定義的枚舉,代表我們不同的數(shù)據(jù)庫。

public enum DataSourceType {
    MYSQL_DATASOURCE1,
    MYSQL_DATASOURCE2,
}

定義數(shù)據(jù)源管理器

由于本人實(shí)力原因,解答不了大家這里的疑惑。大致功能 通過修改本地線程的值,來實(shí)現(xiàn)數(shù)據(jù)源的切換。

@Component
@Primary
public class DataSourceManagement extends AbstractRoutingDataSource {

    public static ThreadLocal<String> flag = new ThreadLocal<>();

    /**
     * 注入數(shù)據(jù)源
     */
    @Resource
    private DataSource mysqlDataSource1;
    /**
     * 注入數(shù)據(jù)源
     */
    @Resource
    private DataSource mysqlDataSource2;

    public DataSourceManagement() {
        flag.set(DataSourceType.MYSQL_DATASOURCE1.name());
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return flag.get();
    }

    @Override
    public void afterPropertiesSet() {
        Map<Object, Object> targetDataSource = new ConcurrentHashMap<>();
        targetDataSource.put(DataSourceType.MYSQL_DATASOURCE1.name(), mysqlDataSource1);
        targetDataSource.put(DataSourceType.MYSQL_DATASOURCE2.name(), mysqlDataSource2);
        // 設(shè)置數(shù)據(jù)源來源
        super.setTargetDataSources(targetDataSource);
        // 設(shè)置默認(rèn)數(shù)據(jù)源
        super.setDefaultTargetDataSource(mysqlDataSource1);
        super.afterPropertiesSet();
    }
}

自定義注解

@target:表示自定義注解能用在哪里

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TargetDataSource {
    DataSourceType value() default DataSourceType.MYSQL_DATASOURCE1;
}

定義切面類

可以看到,我們的切面類采用的是環(huán)繞通知,博主在寫這篇文章之前,做過大量測試,也參考過比較多的文章,總結(jié)以下幾點(diǎn):

  • 采用前置通知,雖然能實(shí)現(xiàn)數(shù)據(jù)源的切換,但是會(huì)導(dǎo)致事務(wù)失效。(推薦視頻)
  • 采用環(huán)繞通知,事務(wù)不會(huì)失效,但是切換數(shù)據(jù)源卻實(shí)現(xiàn)不了。(由Bean的加載順序?qū)е碌?,下文中的@Order就可以解決,@Transactional默認(rèn)級別是最后加載??梢圆榭慈罩拘畔⒅獣?。)
@Component
@Aspect
@Slf4j
@Order(Ordered.LOWEST_PRECEDENCE-1) // Bean加載順序
public class TargetDataSourceAspect {

    @Around("@within(TargetDataSource) || @annotation(TargetDataSource)")
    public Object beforeNoticeUpdateDataSource(ProceedingJoinPoint joinPoint) {
        TargetDataSource annotation = null;
        Class<? extends Object> target = joinPoint.getTarget().getClass();
        if (target.isAnnotationPresent(TargetDataSource.class)) {
            // 判斷類上是否標(biāo)注著注解
            annotation = target.getAnnotation(TargetDataSource.class);
            log.info("類上標(biāo)注了注解");
        } else {
            Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
            if (method.isAnnotationPresent(TargetDataSource.class)) {
                // 判斷方法上是否標(biāo)注著注解,如果類和方法上都沒有標(biāo)注,則報(bào)錯(cuò)
                annotation = method.getAnnotation(TargetDataSource.class);
                log.info("方法上標(biāo)注了注解");
            } else {
                throw new RuntimeException("@TargetDataSource注解只能用于類或者方法上, 錯(cuò)誤出現(xiàn)在:[" +
                        target.toString() + " " + method.toString() + "];");
            }
        }
        // 切換數(shù)據(jù)源
        DataSourceManagement.flag.set(annotation.value().name());
        Object result = null;
        try {
            // 執(zhí)行目標(biāo)代碼
            result = joinPoint.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return result;
    }
}

Service

啟動(dòng)測試類:

import look.word.datasource.service.BookService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;

/**
 * @author : look-word
 * 2022-10-10 23:11
 **/
@SpringBootTest
public class TestBookMapper {
    @Resource
    private BookService bookService;
    @Test
    void updatePrice() {
        System.out.println(bookService.updatePrice(1, 777));
    }
}

觀察執(zhí)行日志可知,數(shù)據(jù)源的切換實(shí)現(xiàn)了,事務(wù)也沒有失效。

到此這篇關(guān)于SpringBoot利用自定義注解實(shí)現(xiàn)多數(shù)據(jù)源的文章就介紹到這了,更多相關(guān)SpringBoot多數(shù)據(jù)源內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論