欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

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

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

第一步

開啟事務(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 //開啟事務(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è)切面類了,用于編寫事務(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í)一般都是通過方法的名字篩選,比如add*save*、delete*等,所以事務(wù)屬性使用的是他的子類NameMatchTransactionAttributeSource

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

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

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

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

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

//通過map集合給多個(gè)方法或者多類方法設(shè)置事務(wù)屬性
public void setNameMap(Map<String, TransactionAttribute> nameMap) {
    nameMap.forEach(this::addTransactionalMethod);
}
//通過方法名稱或一類方法名稱和事務(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中。

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

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

//通過方法名稱設(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ù)行為說明
PROPAGATION_REQUIRED支持當(dāng)前事務(wù),假設(shè)當(dāng)前沒有事務(wù)。就新建一個(gè)事務(wù)
PROPAGATION_SUPPORTS支持當(dāng)前事務(wù),假設(shè)當(dāng)前沒有事務(wù),就以非事務(wù)方式運(yùn)行
PROPAGATION_MANDATORY支持當(dāng)前事務(wù),假設(shè)當(dāng)前沒有事務(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)前沒有事務(wù),則執(zhí)行與PROPAGATION_REQUIRED類似的操作。

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

隔離級(jí)別說明臟讀幻讀不可重復(fù)讀
ISOLATION_DEFAULT默認(rèn)隔離級(jí)別,每種數(shù)據(jù)庫支持的事務(wù)隔離級(jí)別不一樣,根據(jù)使用的數(shù)據(jù)庫改變。---
ISOLATION_READ_UNCOMMITTED讀未提交,即能夠讀取到?jīng)]有被提交的數(shù)據(jù)。
ISOLATION_READ_COMMITTED讀已提交,即能夠讀到那些已經(jīng)提交的數(shù)據(jù)。
ISOLATION_REPEATABLE_READ重復(fù)讀取,即在數(shù)據(jù)讀出來之后加鎖。這個(gè)事務(wù)不結(jié)束,別的事務(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(顧問)是由切入點(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ù),就開啟一個(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ù)地執(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ù)
        txMap.put("noTx*", noTx);
        //寫事務(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)文章

  • Java?NIO?Channel?使用詳情

    Java?NIO?Channel?使用詳情

    這篇文章主要介紹了Java?NIO?Channel?使用詳情,文章圍繞主題展開詳細(xì)內(nèi)容需要的小伙伴可以參考一下,希望對(duì)你的學(xué)習(xí)有所幫助
    2022-04-04
  • Freemaker Replace函數(shù)的正則表達(dá)式運(yùn)用

    Freemaker Replace函數(shù)的正則表達(dá)式運(yùn)用

    這篇文章主要介紹了Freemaker Replace函數(shù)的正則表達(dá)式運(yùn)用 的相關(guān)資料,需要的朋友可以參考下
    2015-12-12
  • 解決IDEA2020.1.2IDEA打不開的問題(最新分享)

    解決IDEA2020.1.2IDEA打不開的問題(最新分享)

    由于idea安裝多了某個(gè)jar,點(diǎn)擊出現(xiàn)讀條后閃退情況,接下來通過本文給大家分享解決IDEA2020.1.2IDEA打不開的問題,非常不錯(cuò),具有一定的參考借鑒價(jià)值,感興趣的朋友跟隨小編一起看看吧
    2020-07-07
  • java ClassLoader機(jī)制詳細(xì)講解

    java ClassLoader機(jī)制詳細(xì)講解

    ClassLoader一個(gè)經(jīng)常出現(xiàn)又讓很多人望而卻步的詞,本文將試圖以最淺顯易懂的方式來講解 ClassLoader,希望能對(duì)不了解該機(jī)制的朋友起到一點(diǎn)點(diǎn)作用
    2016-07-07
  • Spring的事務(wù)控制實(shí)現(xiàn)方法

    Spring的事務(wù)控制實(shí)現(xiàn)方法

    這篇文章主要為大家詳細(xì)介紹了Spring的事務(wù)控制實(shí)現(xiàn)方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • 基于Java快速實(shí)現(xiàn)一個(gè)簡(jiǎn)單版的HashMap詳解

    基于Java快速實(shí)現(xiàn)一個(gè)簡(jiǎn)單版的HashMap詳解

    這篇文章主要為大家詳細(xì)介紹了如何利用Java簡(jiǎn)單實(shí)現(xiàn)一個(gè)底層數(shù)據(jù)結(jié)構(gòu)為數(shù)組?+?鏈表的HashMap,不考慮鏈表長(zhǎng)度超過8個(gè)時(shí)變?yōu)榧t黑樹的情況,需要的可以參考一下
    2023-02-02
  • Spring Bean生命周期之Bean的注冊(cè)詳解

    Spring Bean生命周期之Bean的注冊(cè)詳解

    這篇文章主要為大家詳細(xì)介紹了Spring Bean生命周期之Bean的注冊(cè),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • Java常見的四種負(fù)載均衡算法

    Java常見的四種負(fù)載均衡算法

    本文主要介紹了Java常見的四種負(fù)載均衡算法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • JAVAWEB實(shí)現(xiàn)簡(jiǎn)單的商城項(xiàng)目(一)實(shí)例代碼解析

    JAVAWEB實(shí)現(xiàn)簡(jiǎn)單的商城項(xiàng)目(一)實(shí)例代碼解析

    本文給大家分享一段實(shí)例代碼給大家介紹JAVAWEB實(shí)現(xiàn)簡(jiǎn)單的商城項(xiàng)目(一),非常具有參考價(jià)值,感興趣的朋友一起學(xué)習(xí)吧
    2016-02-02
  • 使用SpringBoot開發(fā)Restful服務(wù)實(shí)現(xiàn)增刪改查功能

    使用SpringBoot開發(fā)Restful服務(wù)實(shí)現(xiàn)增刪改查功能

    Spring Boot是由Pivotal團(tuán)隊(duì)提供的全新框架,其設(shè)計(jì)目的是用來簡(jiǎn)化新Spring應(yīng)用的初始搭建以及開發(fā)過程。這篇文章主要介紹了基于SpringBoot開發(fā)一個(gè)Restful服務(wù),實(shí)現(xiàn)增刪改查功能,需要的朋友可以參考下
    2018-01-01

最新評(píng)論