<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      技術(shù)面:Spring (事務(wù)傳播機(jī)制、事務(wù)失效的原因、BeanFactory和FactoryBean的關(guān)系)

      Spring的事務(wù)傳播機(jī)制

      什么是Spring事務(wù)傳播機(jī)制

      Spring的事務(wù)傳播機(jī)制,主要是用于控制多個事務(wù)方法相互調(diào)用時的事務(wù)行為。
      

      在后端復(fù)雜的業(yè)務(wù)場景中,多個事務(wù)之間的調(diào)用可能會導(dǎo)致事務(wù)的不一致,例如:數(shù)據(jù)重復(fù)提交,數(shù)據(jù)丟失等問題,使用事務(wù)傳播機(jī)制可以避免這些問題的發(fā)生,從而保證事務(wù)的一致性和數(shù)據(jù)的完整性。

      Spring的事務(wù)規(guī)定了7種傳播行為

      Spring 通過 @Transactional 注解的 propagation 屬性來設(shè)置傳播級別

      • Propagation.REQUIRED (默認(rèn))
        • 含義:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則創(chuàng)建一個新的事務(wù)。
        • 特點(diǎn):這是最常用、且Spring默認(rèn)的傳播行為。適用于絕大多數(shù)業(yè)務(wù)場景。
        • 回滾:內(nèi)部方法拋出異常未被捕獲,會導(dǎo)致整個事務(wù)(包括外部方法的操作)回滾。
      • Propagation.REQUIRES_NEW
        • 含義:無論當(dāng)前是否存在事務(wù),都會創(chuàng)建一個新的事務(wù),并將當(dāng)前事務(wù)(如果存在)掛起。
        • 特點(diǎn):創(chuàng)建的是一個完全獨(dú)立的事務(wù),有自己的提交和回滾邊界。
        • 回滾:內(nèi)部新事務(wù)回滾,不影響外部事務(wù)(如果外部事務(wù)正常提交)。
          外部事務(wù)回滾,會將內(nèi)部新事務(wù)也回滾(因?yàn)橥獠渴聞?wù)的回滾會恢復(fù)到調(diào)用 REQUIRES_NEW 方法之前的狀態(tài))。
        • 場景:記錄日志、發(fā)送通知、審計等需要獨(dú)立提交的場景。
      • Propagation.NESTED
        • 含義:如果當(dāng)前存在事務(wù),則在嵌套事務(wù)內(nèi)執(zhí)行(基于數(shù)據(jù)庫的 Savepoint 機(jī)制);如果不存在事務(wù),則創(chuàng)建一個新事務(wù)。
        • 特點(diǎn):不是創(chuàng)建一個真正的新事務(wù),而是在當(dāng)前事務(wù)中設(shè)置一個保存點(diǎn)(Savepoint)。它可以在不破壞外部事務(wù)的情況下進(jìn)行部分回滾。
        • 回滾:內(nèi)部嵌套事務(wù)回滾,只回滾到保存點(diǎn),不影響外部事務(wù)已做的其他操作。外部事務(wù)回滾,會回滾整個事務(wù),包括嵌套事務(wù)的操作。與 REQUIRES_NEW 區(qū)別:NESTED 是“子事務(wù)”,依賴于外部事務(wù);REQUIRES_NEW 是“獨(dú)立事務(wù)”,與外部事務(wù)并列。
      • Propagation.SUPPORTS
        • 含義:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果不存在事務(wù),則以非事務(wù)方式執(zhí)行。
        • 特點(diǎn):對事務(wù)是“可有可無”的態(tài)度。
        • 場景:適用于只讀操作或?qū)κ聞?wù)不敏感的方法。
      • Propagation.NOT_SUPPORTED
        • 含義:以非事務(wù)方式執(zhí)行操作。如果當(dāng)前存在事務(wù),則將當(dāng)前事務(wù)掛起。
        • 特點(diǎn):強(qiáng)制方法不運(yùn)行在事務(wù)中,可以提高性能。
        • 場景:執(zhí)行一些耗時長、不需要事務(wù)保證的操作。
      • Propagation.NEVER
        • 含義:以非事務(wù)方式執(zhí)行,如果當(dāng)前存在事務(wù),則拋出異常。
        • 特點(diǎn):強(qiáng)制禁止在事務(wù)中執(zhí)行此方法。
        • 場景:某些特定操作明確要求不能在事務(wù)上下文中運(yùn)行。
      • Propagation.MANDATORY
        • 含義:方法必須在一個已存在的事務(wù)中執(zhí)行,如果當(dāng)前沒有事務(wù),則拋出異常。
        • 特點(diǎn):強(qiáng)制要求調(diào)用方必須提供一個事務(wù)。
        • 場景:用于那些必須作為更大事務(wù)一部分才能保證一致性的操作

      面試題

      面試官問:一個長的事務(wù)方法a,在讀寫分離的情況下,里面既有讀庫操作,也有寫庫操作,再調(diào)用個讀庫方法b,方法b該用什么傳播機(jī)制呢?
      答:這種情況,讀方法如果是最后一步,直接not_supported就行了,避免讀報錯導(dǎo)致數(shù)據(jù)回滾。如果是中間步驟,最好還是要required,因?yàn)楫惓J⌒枰貪L一下。

      例如:A B C三個操作,C就是最后一步,B就是中間步驟如果一個讀操作在中間(如B操作)失敗了,那么就需要讓A做回滾,因?yàn)镃還沒執(zhí)行,所以A必須回滾才能保證一致性。

      Spring事務(wù)失效可能是哪些原因

      首先,容易造成事務(wù)失效的方式是通過@Transactional注解方式的聲明式事務(wù)。

      @Transactional是基于Spring的AOP來實(shí)現(xiàn)的,而AOP機(jī)制又是基于動態(tài)代理實(shí)現(xiàn)的,如果代理失效那么事務(wù)也就失效了。

      Spring事務(wù)失效的場景

      AOP代理失效

      @Transactional應(yīng)用在非public方法上
      @Service
      public class UserService {
          @Transactional
          private void updateUserData() { // private方法
              // ...
          }
      }
      

      由于代理機(jī)制會為 public 方法創(chuàng)建攔截器,事務(wù)可以正常生效。而非public得方法,JDK代理是不會創(chuàng)建攔截器的,雖然CGLIB可能支持,但行為不一致,不保證生效。
      因此在使用時還是強(qiáng)烈建議放到public方法上。

      類內(nèi)部的調(diào)用,類內(nèi)部方法自調(diào)用,內(nèi)部類方法調(diào)用
      @Service
      public class UserService {
          public void businessMethod() {
              // 1. 執(zhí)行一些業(yè)務(wù)邏輯
              // 2. 調(diào)用本類的事務(wù)方法
              this.transactionalMethod(); // 自調(diào)用,事務(wù)失效
          }
      
          @Transactional
          public void transactionalMethod() {
              // 數(shù)據(jù)庫操作
          }
      }
      
      public class OuterClass{
          private class InnerClass {
              @Transactional
              public void doSomething() {
                  System.out.println("Doing something in inner class...");
              }
          }
          public void invokeInnerClassMethod() {
              InnerClass innerclass = new InnerClass();
              innerclass.doSomething();//調(diào)用內(nèi)部類方法,事務(wù)失效
          }
      }
      

      在對象內(nèi)部調(diào)用其他方法,就會用對象直接調(diào)用了,而不是用代理對象,因此代理會失效。

      static、final方法

      由于static方法是屬于類級別的對象,所以代理對象無法代理,因此AOP也是無效的,因此@Transactional修飾這種方法時,事務(wù)也是會失效的。

      final方法,是固定形式,而AOP的代理是通過子類或?qū)崿F(xiàn)接口來實(shí)現(xiàn)的,final方法無法被子類覆蓋,也無法通過實(shí)現(xiàn)類覆蓋。因此如果將@Transactional修飾這種方法時,事務(wù)也是會失效的。

      不存在代理

      沒有使用Spring管理bean,因此也就不會存在使用AOP來創(chuàng)建代理對象來保證事務(wù)。

      @Transactional配置錯誤

      @Transactional的propagation屬性配置錯誤
      public class UserService{
      	@Transactional(propagation = Propagation.NOT_SUPPORTED)
      	public void notSupportedMethod() {
      	    // 此方法不會運(yùn)行在事務(wù)中
      	}
      }
      

      不同的Propagation屬性決定了事務(wù)的創(chuàng)建和參與方式。例如:Propagation.NOT_SUPPORTEDPropagation.NEVER會掛起或拒絕當(dāng)前事務(wù)。

      @Transactional的rollbackFor設(shè)置錯誤
      public class UserService{
      	@Transactional(rollbackFor = FileNotFoundException.class)
      	public void someMethod(){
      	    // 拋出 IOException
      	    throw new IOException("文件讀取失敗");
      	    // 事務(wù)不會回滾
      	}
      }
      

      rollbackFor配置的異常類型需和方法拋出的異常一致,事務(wù)才會進(jìn)行回滾。改成使用@Transactional(rollbackFor = Exception.class)@Transactional(rollbackFor = IOException.class)即可。

      @Transactional注解引用來源錯誤

      有時候,在寫代碼的時候,由于手快也沒有注意@Transactional注解的引用來源,直接就用了,等出現(xiàn)問題的時候,排查了很久發(fā)現(xiàn)寫的都沒問題,但是還是不生效,然后找別人來幫你看,他上來就看了一下你用的@Transactional,發(fā)現(xiàn)并不是Spring中的,而是其他什么地方的,比如javax.transaction.Transactional ,這樣也會導(dǎo)致事務(wù)失效。

      沒有啟用事務(wù)管理

      • 原因:忘記在Spring配置中啟用事務(wù)管理。
      • 解決方案:
        在Java配置中添加@EnableTransactionManagement。
        在XML配置中添加<tx:annotation-driven />。

      異常被捕獲

      public class UserService{
        @Transactional(rollbackFor = Exception.class)
        public void doSomething() {
            try {
                // doSomething...
            }catch (Exception e){
                System.out.println("Exception:"+e);
            }
        }
      }
      

      異常被捕獲后,不會拋出,也就走不到rollbackFor這樣也就不會進(jìn)行回滾了。

      在多線程環(huán)境下使用了聲明式事務(wù)

      @Transactional的事務(wù)管理使用的是ThreadLocal來存儲事務(wù)上下文,ThreadLocal存儲的變量是線程隔離的,因此每個線程都有自己的事務(wù)上下文副本。所以Spring的聲明式事務(wù)在多線程環(huán)境下會失效的風(fēng)險。

      數(shù)據(jù)庫引擎不支持事務(wù)

      如果使用的數(shù)據(jù)庫表引擎不支持事務(wù)(如MySQL的MyISAM引擎),那么即使Spring配置了事務(wù),也無法回滾。

      解決方案:確保數(shù)據(jù)庫表使用支持事務(wù)的引擎,如MySQL的InnoDB。

      BeanFactory和FactoryBean的關(guān)系

      從名字上看BeanFactory和FactoryBean看著很相似,但是實(shí)際上它倆沒什么關(guān)系,是完全不相關(guān)的兩個接口。

      BeanFactory

      BeanFactory就是Bean的工廠,是整個Spring的IOC其中的一部分,管理Bean的創(chuàng)建和生命周期

      BeanFactory提供了一系列的方法,可以讓我們獲取到具體的Bean實(shí)例。
      你可能沒有直接用過BeanFactory,但是你肯定間接的使用或者看到過。

      applicationContent.getBean(type);
      
      applicationContent.getBean(name);
      

      這些代碼通常用在一些測試用例,或者需要手動從IOC容器中獲取指定的Bean的時候使用。
      通過上面的代碼使用示例也說明了,BeanFactory是IOC容器的一個接口,用來獲取Bean以及管理Bean的依賴注入和生命周期

      FactoryBean

      FactoryBean本質(zhì)是一個特殊的Bean,用于定義一個工廠Bean,可以用來生成某些特定的Bean。

      當(dāng)項(xiàng)目中定義了某一個Bean的時候,如果這個Bean實(shí)現(xiàn)了FactoryBean這個接口,那么使用這個Bean的時候,Spring的IOC容器不會直接返回這個Bean實(shí)例,而是返回FactoryBean的getObject()方法返回的實(shí)體對象。(獲取FactoryBean本身:需要在ID前加&符號(如&myFactoryBean))

      // 定義一個FactoryBean
      public class MyFactoryBean implements FactoryBean<MyObject> {
          public MyObject getObject() {
              return new MyObject(); // 返回實(shí)際對象
          }
          
          public Class<?> getObjectType() {
              return MyObject.class;
          }
          
          public boolean isSingleton() {
              return true;
          }
      }
      
      // 使用
      BeanFactory beanFactory = new DefaultListableBeanFactory();
      // 注冊MyFactoryBean
      beanFactory.registerSingleton("myFactoryBean", new MyFactoryBean());
      
      // 獲取FactoryBean創(chuàng)建的對象
      MyObject obj = (MyObject) beanFactory.getBean("myFactoryBean"); // 返回MyObject實(shí)例
      
      // 獲取FactoryBean本身
      FactoryBean<MyObject> factoryBean = (FactoryBean<MyObject>) beanFactory.getBean("&myFactoryBean");
      

      FactoryBean常用于創(chuàng)建需要特殊初始化邏輯的Bean,如Spring AOP代理、JNDI數(shù)據(jù)源,kafka,Dubbo中都用FactoryBean與Spring做集成。

      總結(jié)

      特性 BeanFactory FactoryBean
      本質(zhì) Spring容器核心接口 一個特殊Bean
      名稱含義 Bean的工廠 工廠類型的Bean
      獲取對象 獲取Bean實(shí)例 獲取getObject()返回的對象
      是否為容器 否(它是容器中的一個Bean)
      主要用途 管理所有Bean 自定義特定Bean的創(chuàng)建邏輯
      posted @ 2025-10-10 18:57  紀(jì)莫  閱讀(247)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产短视频一区二区三区| 国产麻豆精品一区一区三区| 日本久久99成人网站| 真人无码作爱免费视频| 丁香五月亚洲综合在线国内自拍 | 亚洲精品乱码久久久久久蜜桃图片| 日本视频一两二两三区| 亚洲色大成网站www永久男同| 老熟妇仑乱一区二区视頻| 中文字幕一区二区三区麻豆| 中文字幕精品亚洲二区| 不卡一区二区国产精品| 三级国产在线观看| 好爽好紧好大的免费视频| 亚洲一二区在线视频播放| 午夜福利偷拍国语对白| 色av专区无码影音先锋| 津市市| 欧洲熟妇色自偷自拍另类| 中文字幕日韩精品人妻| 成人午夜电影福利免费| 自拍偷拍视频一区二区三区| 精品一精品国产一级毛片| 欧美videos粗暴| 欧美大屁股xxxx高跟欧美黑人| 91精品午夜福利在线观看| 日本高清视频网站www| 日本高清中文字幕免费一区二区| 亚洲男人天堂一级黄色片| 青草99在线免费观看| 国产精品久久无码不卡黑寡妇| 亚洲二区中文字幕在线| 国产高清在线男人的天堂| 亚洲熟妇无码av另类vr影视 | 麻江县| 18禁在线一区二区三区| 亚洲成在人线AV品善网好看| 麻豆一区二区中文字幕| 97国产精品人人爽人人做| 九九九国产| 国产高清精品在线91|