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

探索Java中private方法添加@Transactional事務(wù)未生效原因

 更新時(shí)間:2021年11月24日 14:41:05   作者:JavaEdge.  
你又遇到過(guò)明明給private方法添加了@Transactional但是事務(wù)依然沒(méi)有生效的情況嗎,具體原因本篇文章將詳細(xì)告訴你,有需要的朋友跟著小編往下看吧

現(xiàn)在產(chǎn)品期望用戶創(chuàng)建和保存邏輯分離:把User實(shí)例的創(chuàng)建和保存邏輯拆到兩個(gè)方法分別進(jìn)行。然后,把事務(wù)的注解 @Transactional 加在保存數(shù)據(jù)庫(kù)的方法上。

@Service
public class StudentService {
    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private StudentService studentService;

    public void saveStudent(String realname) throws Exception {
        Student student = new Student();
        student.setRealname(realname);
        studentService.doSaveStudent(student);
    }

    @Transactional
    private void doSaveStudent(Student student) throws Exception {
        studentMapper.saveStudent(student);
        if (student.getRealname().equals("小明")) {
            throw new RuntimeException("該用戶已存在");
        }
    }
}

執(zhí)行程序,異常正常拋出

事務(wù)未回滾

源碼解析

debug:

前一段是 Spring 創(chuàng)建 Bean 的過(guò)程。當(dāng) Bean 初始化之后,開(kāi)始嘗試代理操作,這是從如下方法開(kāi)始處理的:

AbstractAutoProxyCreator#postProcessAfterInitialization

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
   if (bean != null) {
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
      if (this.earlyProxyReferences.remove(cacheKey) != bean) {
         return wrapIfNecessary(bean, beanName, cacheKey);
      }
   }
   return bean;
}

繼續(xù) debug,直到

AopUtils#canApply

針對(duì)切面定義里的條件,確定這個(gè)方法是否可被應(yīng)用創(chuàng)建成代理。有段 methodMatcher.matches(method, targetClass) 判斷這個(gè)方法是否符合這樣的條件:

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
   // ...
   for (Class<?> clazz : classes) {
      Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
      for (Method method : methods) {
         if (introductionAwareMethodMatcher != null ?
               introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
               methodMatcher.matches(method, targetClass)) {
            return true;
         }
      }
   }
   return false;
}

從 matches() 調(diào)用到

AbstractFallbackTransactionAttributeSource#getTransactionAttribute

獲取注解中的事務(wù)屬性,根據(jù)屬性確定事務(wù)的策略。

接著調(diào)用到

computeTransactionAttribute

根據(jù)方法和類的類型確定是否返回事務(wù)屬性:

當(dāng)上圖中條件判斷結(jié)果為 true,則返回 null,表明該方法不會(huì)被代理,從而導(dǎo)致事務(wù)注解不會(huì)生效。

那到底是不是 true 呢?

條件1:allowPublicMethodsOnly()

AnnotationTransactionAttributeSource#publicMethodsOnly屬性值

publicMethodsOnly 是通過(guò) AnnotationTransactionAttributeSource 的構(gòu)造方法初始化的,默認(rèn)為 true。

條件2:Modifier.isPublic()

根據(jù)傳入的 method.getModifiers() 獲取方法的修飾符,該修飾符是 java.lang.reflect.Modifier 的靜態(tài)屬性,對(duì)應(yīng)的幾類修飾符分別是:

  • PUBLIC: 1
  • PRIVATE: 2
  • PROTECTED: 4

這里做了一個(gè)位運(yùn)算,只有當(dāng)傳入的方法修飾符是 public 類型的時(shí)候,才返回 true

綜上兩個(gè)條件,只有當(dāng)注解為事務(wù)方法為 public 才會(huì)被 Spring 處理。

修正

只需將修飾符從 private 改成 public,其實(shí)該問(wèn)題 IDEA 也會(huì)告警,一般都會(huì)避免。

調(diào)用這個(gè)加了事務(wù)注解的方法,必須是調(diào)用被 Spring AOP 代理過(guò)的方法:不能通過(guò)類的內(nèi)部調(diào)用或通過(guò) this 調(diào)用。所以我們的案例的StudentService,它Autowired了自身(StudentService)的一個(gè)實(shí)例來(lái)完成代理方法的調(diào)用。

到此這篇關(guān)于探索Java中private方法添加@Transactional事務(wù)未生效原因的文章就介紹到這了,更多相關(guān)Java private方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring Cloud Alibaba Nacos Config進(jìn)階使用

    Spring Cloud Alibaba Nacos Config進(jìn)階使用

    這篇文章主要介紹了Spring Cloud Alibaba Nacos Config進(jìn)階使用,文中使用企業(yè)案例,圖文并茂的展示了Nacos Config的使用,感興趣的小伙伴可以看一看
    2021-08-08
  • 完美解決IDEA Ctrl+Shift+f快捷鍵突然無(wú)效的問(wèn)題

    完美解決IDEA Ctrl+Shift+f快捷鍵突然無(wú)效的問(wèn)題

    這篇文章主要介紹了完美解決IDEA Ctrl+Shift+f快捷鍵突然無(wú)效的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • 淺談JavaIO之try with底層原理

    淺談JavaIO之try with底層原理

    眾所周知,所有被打開(kāi)的系統(tǒng)資源,比如流、文件或者Socket連接等,都需要被開(kāi)發(fā)者手動(dòng)關(guān)閉,否則隨著程序的不斷運(yùn)行,資源泄露將會(huì)累積成重大的生產(chǎn)事故。本文將介紹JavaIO之try with底層原理。
    2021-06-06
  • 單元測(cè)試 @mock與@SpringBootTest的使用

    單元測(cè)試 @mock與@SpringBootTest的使用

    這篇文章主要介紹了單元測(cè)試 @mock與@SpringBootTest的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • java解析excel文件的方法

    java解析excel文件的方法

    這篇文章主要介紹了java解析excel文件的方法,這里整理相關(guān)的代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-02-02
  • Java集合TreeSet用法詳解

    Java集合TreeSet用法詳解

    本文詳細(xì)講解了Java集合TreeSet用法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-12-12
  • Java中從Integer到Date的轉(zhuǎn)換方法

    Java中從Integer到Date的轉(zhuǎn)換方法

    這篇文章主要介紹了Java中integer怎么轉(zhuǎn)換date,在Java中,如果我們有一個(gè)Integer類型的數(shù)據(jù),想要將其轉(zhuǎn)換為Date類型,本文給大家介紹了實(shí)現(xiàn)方法,并通過(guò)代碼示例講解的非常詳細(xì),需要的朋友可以參考下
    2024-05-05
  • Spring自帶定時(shí)任務(wù)@Scheduled注解實(shí)例講解

    Spring自帶定時(shí)任務(wù)@Scheduled注解實(shí)例講解

    這篇文章主要介紹了Spring自帶定時(shí)任務(wù)@Scheduled注解的相關(guān)知識(shí),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-06-06
  • 盤點(diǎn)SpringBoot中@Async注解的遇到的坑點(diǎn)及解決辦法

    盤點(diǎn)SpringBoot中@Async注解的遇到的坑點(diǎn)及解決辦法

    SpringBoot是一個(gè)流行的Java開(kāi)發(fā)框架,在異步編程方面,Spring Boot提供了@Async注解,它能夠讓方法異步執(zhí)行,然而,在使用@Async注解時(shí),有一些潛在的坑需要注意,本文將深入探討Spring Boot中使用@Async注解時(shí)可能遇到的8大坑點(diǎn),并提供相應(yīng)的解決方案
    2024-03-03
  • IntelliJ IDEA中代碼一鍵生成方法

    IntelliJ IDEA中代碼一鍵生成方法

    EasyCode 是基于 IntelliJ IDEA 開(kāi)發(fā)的代碼生成插件,支持自定義任意模板(Java,html,js,xml),這篇文章主要介紹了IntelliJ IDEA中代碼一鍵生成方法,需要的朋友可以參考下
    2020-02-02

最新評(píng)論