最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot AOP如何配置全局事務(wù)

 更新時(shí)間:2024年05月11日 11:44:03   作者:X爪哇程序猿  
這篇文章主要介紹了SpringBoot AOP如何配置全局事務(wù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

SpringBoot的出現(xiàn)使得項(xiàng)目中使用事務(wù)變得非常簡(jiǎn)單,有兩種使用方式,適合小型項(xiàng)目的注解事務(wù)(聲明式事務(wù)管理),適合大型項(xiàng)目的全局事務(wù)。

1、注解事務(wù)(次要)

注解事務(wù)使用只用兩步,開(kāi)啟事務(wù)注解功能,使用事務(wù)注解功能,并且每步都只有使用一個(gè)注解。

第一步

開(kāi)啟事務(wù)注解功能@EnableTransactionManagement

在主啟動(dòng)類中添加注解@EnableTransactionManagement即可。

package com.gx;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@EnableTransactionManagement //開(kāi)啟事務(wù)注解功能
@SpringBootApplication
public class Ch09SpringbootTransAnnoApplication {

    public static void main(String[] args) {
        SpringApplication.run(Ch09SpringbootTransAnnoApplication.class, args);
    }

}

第二步

使用事務(wù)注解功能@Transactional

在service接口實(shí)現(xiàn)類或接口實(shí)現(xiàn)類方法上添加@Transactional即可。

package com.gx.service.impl;

import com.gx.service.StudentService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.gx.domain.Student;

@Service
public class StudentServiceImpl implements StudentService {

    @Transactional //使用注解事務(wù)
    @Override
    public String addStudent(Student student) {
        //業(yè)務(wù)方法
    }
}

注意事項(xiàng):@Transactional必須添加在public修飾的方法上。

2、全局事務(wù)(主要)

SpringBoot全局事務(wù)主要使用AOP切面編程。

第一步

創(chuàng)建切面類@Aspect。

創(chuàng)建一個(gè)普通的類,加上@Aspect后該類就是一個(gè)切面類了,用于編寫(xiě)事務(wù)功能。

同時(shí)還需要把該切面類定義為一個(gè)配置類,添加注解@Configuration即可。

注意事項(xiàng):

1、@Aspect將該類定義為切面類,把當(dāng)前類作為一個(gè)切面被容器讀取。

? 2、@Configuration將該類定義為配置類,配置spring容器,注入bean

package com.gx.config;

import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.annotation.Configuration;

@Aspect //定義切面類,把當(dāng)前類標(biāo)識(shí)為一個(gè)切面供容器讀取
@Configuration //定義配置類
public class TransactionAdviceConfig {
	//增強(qiáng)方法
}

第二步

創(chuàng)建第一個(gè)方法,返回事務(wù)攔截器(TransactionInterceptor),聲明業(yè)務(wù)方法的事務(wù)屬性,并且注冊(cè)到bean中。

需要返回事務(wù)攔截器TransactionInterceptor,就需要new一個(gè)TransactionInterceptor。

根據(jù)TransactionInterceptor的類可得知,創(chuàng)建一個(gè)TransactionInterceptor目前只有兩個(gè)方法。

public TransactionInterceptor() {
    
}

public TransactionInterceptor(TransactionManager ptm, TransactionAttributeSource tas) {
    this.setTransactionManager(ptm);
    this.setTransactionAttributeSource(tas);
}

要使用事務(wù),就要有事務(wù)管理器TransactionManager和事務(wù)屬性TransactionAttributeSource。

配置事務(wù)屬性時(shí)一般都是通過(guò)方法的名字篩選,比如add*、save*、delete*等,所以事務(wù)屬性使用的是他的子類NameMatchTransactionAttributeSource。

//事務(wù)管理器
@Autowired
private TransactionManager transactionManager;

@Bean
public TransactionInterceptor txAdvice() {
    //聲明一個(gè)通過(guò)方法名字配置事務(wù)屬性的對(duì)象
	NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
	//返回一個(gè)事務(wù)攔截器
    return new TransactionInterceptor(transactionManager, source);
}

通過(guò)方法名稱設(shè)置業(yè)務(wù)方法事務(wù)屬性。

NameMatchTransactionAttributeSource類中我們使用的頻繁的就兩個(gè)方法。

setNameMap其實(shí)就是addTransactionalMethod的集合。

//通過(guò)map集合給多個(gè)方法或者多類方法設(shè)置事務(wù)屬性
public void setNameMap(Map<String, TransactionAttribute> nameMap) {
    nameMap.forEach(this::addTransactionalMethod);
}
//通過(guò)方法名稱或一類方法名稱和事務(wù)屬性,給一個(gè)方法或一類方法設(shè)置事務(wù)屬性
public void addTransactionalMethod(String methodName, TransactionAttribute attr) {
    if (logger.isDebugEnabled()) {
        logger.debug("Adding transactional method [" + methodName + "] with attribute [" + attr + "]");
    }
    if (this.embeddedValueResolver != null && attr instanceof DefaultTransactionAttribute) {
        ((DefaultTransactionAttribute) attr).resolveAttributeStrings(this.embeddedValueResolver);
    }
    this.nameMap.put(methodName, attr);
}

設(shè)置事務(wù)屬性。

TransactionAttribute:事務(wù)屬性,有很多實(shí)現(xiàn)的實(shí)現(xiàn)類,一般使用基于規(guī)則的事務(wù)屬性RuleBasedTransactionAttribute。

功能大部分在他的父類DefaultTransactionDefinition中。

只寫(xiě)一小部分,其他可以根據(jù)業(yè)務(wù)需求寫(xiě)事務(wù)屬性。

//配置一個(gè)事務(wù)屬性(只讀)
RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();
//是否只讀
readOnlyTx.setReadOnly(true);
//事務(wù)傳播行為
readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

//通過(guò)方法名稱設(shè)置業(yè)務(wù)方法事務(wù)屬性
Map<String, TransactionAttribute> txMap = new HashMap<>();
txMap.put("get*", readOnlyTx);

再添加到NameMatchTransactionAttributeSource

source.setNameMap(txMap);

設(shè)置事務(wù)屬性的方法

  • 1、事務(wù)傳播行為 setPropagationBehavior();
  • 2、事務(wù)隔離級(jí)別 setIsolationLevel();
  • 3、事務(wù)超時(shí)時(shí)間 setTimeout();
  • 4、事務(wù)只讀 setReadOnly();
  • 5、設(shè)置事務(wù)名稱 setName();
  • 6、設(shè)置回滾規(guī)則 setRollbackRules();

事務(wù)屬性。(擴(kuò)展)

事務(wù)傳播行為

事務(wù)行為說(shuō)明
PROPAGATION_REQUIRED支持當(dāng)前事務(wù),假設(shè)當(dāng)前沒(méi)有事務(wù)。就新建一個(gè)事務(wù)
PROPAGATION_SUPPORTS支持當(dāng)前事務(wù),假設(shè)當(dāng)前沒(méi)有事務(wù),就以非事務(wù)方式運(yùn)行
PROPAGATION_MANDATORY支持當(dāng)前事務(wù),假設(shè)當(dāng)前沒(méi)有事務(wù),就拋出異常
PROPAGATION_REQUIRES_NEW新建事務(wù),假設(shè)當(dāng)前存在事務(wù)。把當(dāng)前事務(wù)掛起
PROPAGATION_NOT_SUPPORTED以非事務(wù)方式運(yùn)行操作。假設(shè)當(dāng)前存在事務(wù),就把當(dāng)前事務(wù)掛起
PROPAGATION_NEVER以非事務(wù)方式運(yùn)行,假設(shè)當(dāng)前存在事務(wù),則拋出異常
PROPAGATION_NESTED如果當(dāng)前存在事務(wù),則在嵌套事務(wù)內(nèi)執(zhí)行。如果當(dāng)前沒(méi)有事務(wù),則執(zhí)行與PROPAGATION_REQUIRED類似的操作。

事務(wù)隔離級(jí)別,事務(wù)的隔離級(jí)別只用4種但是spring提供有5種。(spring的隔離級(jí)別名字與數(shù)據(jù)庫(kù)中的不一樣)

隔離級(jí)別說(shuō)明臟讀幻讀不可重復(fù)讀
ISOLATION_DEFAULT默認(rèn)隔離級(jí)別,每種數(shù)據(jù)庫(kù)支持的事務(wù)隔離級(jí)別不一樣,根據(jù)使用的數(shù)據(jù)庫(kù)改變。---
ISOLATION_READ_UNCOMMITTED讀未提交,即能夠讀取到?jīng)]有被提交的數(shù)據(jù)。
ISOLATION_READ_COMMITTED讀已提交,即能夠讀到那些已經(jīng)提交的數(shù)據(jù)。
ISOLATION_REPEATABLE_READ重復(fù)讀取,即在數(shù)據(jù)讀出來(lái)之后加鎖。這個(gè)事務(wù)不結(jié)束,別的事務(wù)無(wú)法操作這條數(shù)據(jù)。
ISOLATION_SERIALIZABLE串行化,最高的事務(wù)隔離級(jí)別,不管多少事務(wù),挨個(gè)運(yùn)行完一個(gè)事務(wù)的所有子事務(wù)之后才可以執(zhí)行另外一個(gè)事務(wù)里面的所有子事務(wù)。

第三步

配置適配器(Advisor),增強(qiáng)事務(wù)。

創(chuàng)建適配器(一個(gè)普通的方法返回Advisor)。

Advisor(顧問(wèn))是由切入點(diǎn)和Advice(通知)組成的,但是Advisor是一個(gè)接口,需要實(shí)現(xiàn)它實(shí)現(xiàn)類DefaultPointcutAdvisor,并且傳入?yún)?shù)切入點(diǎn)和Adivce。

@Bean
public Advisor txAdviceAdvisor() {
    //增強(qiáng)事務(wù),關(guān)聯(lián)切入點(diǎn)和事務(wù)屬性
    return new DefaultPointcutAdvisor(切入點(diǎn), Advice);
}

配置切入點(diǎn)。

//配置切入點(diǎn)表達(dá)式 : 指定哪些包中的類使用事務(wù),設(shè)置為靜態(tài)類常量
private static final String AOP_POINTCUT_EXPRESSION = "execution (* com.***.service.*.*(..))";

//一下內(nèi)容放在適配器方法內(nèi)
//配置事務(wù)切入點(diǎn)表達(dá)式
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(AOP_POINTCUT_EXPRESSION);

關(guān)聯(lián)切入點(diǎn)和Advice。

//增強(qiáng)事務(wù),關(guān)聯(lián)切入點(diǎn)和事務(wù)屬性
return new DefaultPointcutAdvisor(pointcut, txAdvice());

第四步

重啟測(cè)試!

最后奉上aop全局事務(wù)全部代碼

package com.gx.config;

import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.interceptor.*;

import javax.sql.DataSource;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

@Aspect //定義切面類,把當(dāng)前類標(biāo)識(shí)為一個(gè)切面供容器讀取
@Configuration //定義配置類
public class TransactionAdviceConfig {

    //事務(wù)的超時(shí)時(shí)間為10秒
    private static final int TX_METHOD_TIMEOUT = 10;

    //配置切入點(diǎn)表達(dá)式 : 指定哪些包中的類使用事務(wù)
    private static final String AOP_POINTCUT_EXPRESSION = "execution (* com.***.service.*.*(..))";

    //事務(wù)管理器
    @Autowired
    private TransactionManager transactionManager;
    /**
     * 聲明業(yè)務(wù)方法的事務(wù)屬性
     */
    @Bean
    public TransactionInterceptor txAdvice() {

        /**
         * 這里配置只讀事務(wù)
         */
        RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();
        readOnlyTx.setReadOnly(true);//是否只讀
        readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);//事務(wù)的傳播行為

        /**
         * 必須帶事務(wù)
         * 當(dāng)前存在事務(wù)就使用當(dāng)前事務(wù),當(dāng)前不存在事務(wù),就開(kāi)啟一個(gè)新的事務(wù)
         */
        RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute();
        //檢查型異常也回滾
        requiredTx.setRollbackRules(
                Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
        requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        requiredTx.setTimeout(TX_METHOD_TIMEOUT);

        /**
         * 無(wú)事務(wù)地執(zhí)行,掛起任何存在的事務(wù)
         */
        RuleBasedTransactionAttribute noTx = new RuleBasedTransactionAttribute();
        noTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);

        /**
         * 設(shè)置方法對(duì)應(yīng)的事務(wù)
         */
        Map<String, TransactionAttribute> txMap = new HashMap<>();
        //只讀事務(wù)
        txMap.put("get*", readOnlyTx);
        txMap.put("query*", readOnlyTx);
        txMap.put("find*", readOnlyTx);
        txMap.put("list*", readOnlyTx);
        txMap.put("count*", readOnlyTx);
        txMap.put("exist*", readOnlyTx);
        txMap.put("search*", readOnlyTx);
        txMap.put("fetch*", readOnlyTx);
        //無(wú)事務(wù)
        txMap.put("noTx*", noTx);
        //寫(xiě)事務(wù)
        txMap.put("add*", requiredTx);
        txMap.put("save*", requiredTx);
        txMap.put("insert*", requiredTx);
        txMap.put("update*", requiredTx);
        txMap.put("modify*", requiredTx);
        txMap.put("delete*", requiredTx);
		
        NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
        source.setNameMap(txMap);
        
		//返回事務(wù)攔截器
        return new TransactionInterceptor(transactionManager, source);
    }

    @Bean
    public Advisor txAdviceAdvisor() {
        //配置事務(wù)切入點(diǎn)表達(dá)式
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
        //增強(qiáng)事務(wù),關(guān)聯(lián)切入點(diǎn)和事務(wù)屬性
        return new DefaultPointcutAdvisor(pointcut, txAdvice());
    }
}

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringBoot項(xiàng)目集成Flyway詳細(xì)過(guò)程

    SpringBoot項(xiàng)目集成Flyway詳細(xì)過(guò)程

    今天帶大家學(xué)習(xí)SpringBoot項(xiàng)目集成Flyway詳細(xì)過(guò)程,文中有非常詳細(xì)的介紹及代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很好地幫助,需要的朋友可以參考下
    2021-05-05
  • java多線程JUC常用輔助類詳解

    java多線程JUC常用輔助類詳解

    這篇文章主要為大家介紹了java多線程及并發(fā)編程中JUC常用輔助類,文中附含詳細(xì)示例代碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2021-09-09
  • SpringBoot中實(shí)現(xiàn)接收文件和對(duì)象

    SpringBoot中實(shí)現(xiàn)接收文件和對(duì)象

    這篇文章主要介紹了SpringBoot實(shí)現(xiàn)接收文件和對(duì)象,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • Java SSM框架如何添加寫(xiě)日志功能

    Java SSM框架如何添加寫(xiě)日志功能

    這篇文章主要介紹了Java SSM框架如何添加寫(xiě)日志功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Java中將String類型轉(zhuǎn)換為int類型的五種方法及常見(jiàn)問(wèn)題分析

    Java中將String類型轉(zhuǎn)換為int類型的五種方法及常見(jiàn)問(wèn)題分析

    在Java中將String類型轉(zhuǎn)換為int類型是一個(gè)常見(jiàn)的操作,因?yàn)樵趯?shí)際開(kāi)發(fā)中,我們經(jīng)常需要從用戶輸入或者外部數(shù)據(jù)源中獲取字符串形式的數(shù)字,并將其轉(zhuǎn)換為整數(shù)進(jìn)行計(jì)算和處理,在Java中,有幾種方法可以實(shí)現(xiàn)這種轉(zhuǎn)換,下面我將逐一介紹這些方法,需要的朋友可以參考下
    2025-06-06
  • 從?JVM?中深入探究?Synchronized作用及原理

    從?JVM?中深入探究?Synchronized作用及原理

    這篇文章主要為大家介紹了從?JVM?中深入探究?Synchronized作用及原理,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • Springboot詳解如何整合使用Thymeleaf

    Springboot詳解如何整合使用Thymeleaf

    這篇文章主要分享了Spring Boot整合使用Thymeleaf,Thymeleaf是新一代的Java模板引擎,類似于Velocity、FreeMarker等傳統(tǒng)引擎,關(guān)于其更多相關(guān)內(nèi)容,需要的小伙伴可以參考一下
    2022-06-06
  • 詳解Spring Boot 定時(shí)任務(wù)的實(shí)現(xiàn)方法

    詳解Spring Boot 定時(shí)任務(wù)的實(shí)現(xiàn)方法

    最近在用SpringBoot寫(xiě)一個(gè)關(guān)于定時(shí)項(xiàng)目的時(shí)候遇到一個(gè)問(wèn)題,下面小編把如何處理定時(shí)任務(wù)的解決思路分享給大家 ,需要的朋友參考下
    2017-05-05
  • java?Comparable和Comparator的區(qū)別及作用面試精講

    java?Comparable和Comparator的區(qū)別及作用面試精講

    這篇文章主要為大家介紹了java?Comparable和Comparator的區(qū)別及作用面試精講,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • FileOutputStream文件寫(xiě)入類實(shí)現(xiàn)方式

    FileOutputStream文件寫(xiě)入類實(shí)現(xiàn)方式

    這篇文章主要介紹了FileOutputStream文件寫(xiě)入類實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2026-03-03

最新評(píng)論

临桂县| 库车县| 拉萨市| 安康市| 丹寨县| 中超| 南澳县| 霍州市| 桦南县| 广水市| 宜君县| 宜君县| 鄄城县| 高密市| 嫩江县| 黄骅市| 抚顺市| 深泽县| 屏山县| 昭平县| 调兵山市| 丹寨县| 无极县| 舒城县| 徐水县| 巴彦淖尔市| 洛隆县| 保靖县| 诸暨市| 丹寨县| 仙桃市| 漳浦县| 舒兰市| 闵行区| 瑞金市| 金川县| 醴陵市| 井冈山市| 双桥区| 武威市| 博爱县|