1. 程式人生 > >spring宣告式事務 同一類內方法呼叫事務失效

spring宣告式事務 同一類內方法呼叫事務失效

前些日子一朋友在需要在目標物件中進行自我呼叫,且需要實施相應的事務定義,且網上的一種通過BeanPostProcessor的解決方案是存在問題的。因此專門寫此篇帖子分析why。

1、預備知識

使用AOP 代理後的方法呼叫執行流程,如圖所示



也就是說我們首先呼叫的是AOP代理物件而不是目標物件,首先執行事務切面,事務切面內部通過TransactionInterceptor環繞增強進行事務的增強,即進入目標方法之前開啟事務,退出目標方法時提交/回滾事務。

2、測試程式碼準備

Java程式碼  收藏程式碼
  1. public interface AService {  
  2.     public void a();  
  3.     public void b();  
  4. }  
  5. @Service()  
  6. public class AServiceImpl1 implements AService{  
  7.     @Transactional(propagation = Propagation.REQUIRED)  
  8.     public void a() {  
  9.         this.b();  
  10.     }  
  11.     @Transactional(propagation = Propagation.REQUIRES_NEW)  
  12.     public void b() {  
  13.     }  
  14. }  

3、問題

目標物件內部的自我呼叫將無法實施切面中的增強,如圖所示


 

此處的this指向目標物件,因此呼叫this.b()將不會執行b事務切面,即不會執行事務增強,因此b方法的事務定義“@Transactional(propagation = Propagation.REQUIRES_NEW)”將不會實施,即結果是b和a方法的事務定義是一樣的,可以從以下日誌看出:

 org.springframework.transaction.annotation.AnnotationTransactionAttributeSource Adding transactional method 'a' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''

org.springframework.beans.factory.support.DefaultListableBeanFactory Returning cached instance of singleton bean 'txManager'

org.springframework.orm.hibernate4.HibernateTransactionManager Creating new transaction with name [com.sishuok.service.impl.AServiceImpl1.a]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''  -----建立a方法事務

org.springframework.orm.hibernate4.HibernateTransactionManager Opened new Session …… for Hibernate transaction  ---開啟Session

……

org.springframework.transaction.support.TransactionSynchronizationManager Initializing transaction synchronization

org.springframework.transaction.interceptor.TransactionInterceptor Getting transaction for [com.sishuok.service.impl.AServiceImpl1.a]

org.springframework.transaction.interceptor.TransactionInterceptor Completing transaction for [com.sishuok.service.impl.AServiceImpl1.a] ----完成a方法事務

org.springframework.orm.hibernate4.HibernateTransactionManager Triggering beforeCommit synchronization

org.springframework.orm.hibernate4.HibernateTransactionManager Triggering beforeCompletion synchronization

org.springframework.orm.hibernate4.HibernateTransactionManager Initiating transaction commit

org.springframework.orm.hibernate4.HibernateTransactionManager Committing Hibernate transaction on Session ……---提交a方法事務

org.springframework.orm.hibernate4.HibernateTransactionManager Rolling back Hibernate transaction on Session ……---如果有異常將回滾a方法事務

org.springframework.orm.hibernate4.HibernateTransactionManager Triggering afterCommit synchronization

org.springframework.orm.hibernate4.HibernateTransactionManager Triggering afterCompletion synchronization

org.springframework.transaction.support.TransactionSynchronizationManager Clearing transaction synchronization

……

org.springframework.orm.hibernate4.HibernateTransactionManager Closing Hibernate Session …… after transaction     --關閉Session

我們可以看到事務切面只對a方法進行了事務增強,沒有對b方法進行增強。

3、解決方案

此處a方法中呼叫b方法時,只要通過AOP代理呼叫b方法即可走事務切面,即可以進行事務增強,如下所示:

Java程式碼  收藏程式碼
  1. public void a() {  
  2. aopProxy.b();//即呼叫AOP代理物件的b方法即可執行事務切面進行事務增強  
  3. }  

判斷一個Bean是否是AOP代理物件可以使用如下三種方法:

AopUtils.isAopProxy(bean)        : 是否是代理物件;

AopUtils.isCglibProxy(bean)       : 是否是CGLIB方式的代理物件;

AopUtils.isJdkDynamicProxy(bean) : 是否是JDK動態代理方式的代理物件;

3.1、通過ThreadLocal暴露Aop代理物件

1、開啟暴露Aop代理到ThreadLocal支援(如下配置方式從spring3開始支援)

Java程式碼  收藏程式碼
  1. <aop:aspectj-autoproxy expose-proxy="true"/><!—註解風格支援-->  
Java程式碼  收藏程式碼
  1. <aop:config expose-proxy="true"><!—xml風格支援-->   

2、修改我們的業務實現類

this.b();-----------修改為--------->((AService) AopContext.currentProxy()).b();

3、執行測試用例,日誌如下

org.springframework.beans.factory.support.DefaultListableBeanFactory Returning cached instance of singleton bean 'txManager'

org.springframework.orm.hibernate4.HibernateTransactionManager Creating new transaction with name [com.sishuok.service.impl.AServiceImpl2.a]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''   -----建立a方法事務

org.springframework.orm.hibernate4.HibernateTransactionManager Opened new Session ……for Hibernate transaction  --開啟a Session

org.springframework.orm.hibernate4.HibernateTransactionManager Preparing JDBC Connection of Hibernate Session ……

org.springframework.orm.hibernate4.HibernateTransactionManager Exposing Hibernate transaction as JDBC transaction ……

……

org.springframework.transaction.support.TransactionSynchronizationManager Initializing transaction synchronization

org.springframework.transaction.interceptor.TransactionInterceptor Getting transaction for [com.sishuok.service.impl.AServiceImpl2.a]

org.springframework.transaction.annotation.AnnotationTransactionAttributeSource Adding transactional method 'b' with attribute: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT; ''

……

org.springframework.orm.hibernate4.HibernateTransactionManager Suspending current transaction, creating new transaction with name [com.sishuok.service.impl.AServiceImpl2.b]  -----建立b方法事務(並暫停a方法事務)

……

org.springframework.orm.hibernate4.HibernateTransactionManager Opened new Session  for Hibernate transaction  ---開啟b Session

……

org.springframework.transaction.support.TransactionSynchronizationManager Initializing transaction synchronization

org.springframework.transaction.interceptor.TransactionInterceptor Getting transaction for [com.sishuok.service.impl.AServiceImpl2.b]

org.springframework.transaction.interceptor.TransactionInterceptor Completing transaction for [com.sishuok.service.impl.AServiceImpl2.b] ----完成b方法事務

org.springframework.orm.hibernate4.HibernateTransactionManager Triggering beforeCommit synchronization

org.springframework.orm.hibernate4.HibernateTransactionManager Triggering beforeCompletion synchronization

org.springframework.orm.hibernate4.HibernateTransactionManager Initiating transaction commit

org.springframework.orm.hibernate4.HibernateTransactionManager Committing Hibernate transaction on Session …… ---提交b方法事務

org.springframework.orm.hibernate4.HibernateTransactionManager Triggering afterCommit synchronization

org.springframework.orm.hibernate4.HibernateTransactionManager Triggering afterCompletion synchronization

org.springframework.transaction.support.TransactionSynchronizationManager Clearing transaction synchronization

……

org.springframework.orm.hibernate4.HibernateTransactionManager Closing Hibernate Session …… after transaction  --關閉 b Session

-----到此b方法事務完畢

org.springframework.orm.hibernate4.HibernateTransactionManager Resuming suspended transaction after completion of inner transaction ---恢復a方法事務

……

org.springframework.transaction.support.TransactionSynchronizationManager Initializing transaction synchronization

org.springframework.transaction.interceptor.TransactionInterceptor Completing transaction for [com.sishuok.service.impl.AServiceImpl2.a] ----完成a方法事務

org.springframework.orm.hibernate4.HibernateTransactionManager Triggering beforeCommit synchronization

org.springframework.orm.hibernate4.HibernateTransactionManager Triggering beforeCompletion synchronization

org.springframework.orm.hibernate4.HibernateTransactionManager Initiating transaction commit

org.springframework.orm.hibernate4.HibernateTransactionManager Committing Hibernate transaction on Session ……---提交a方法事務

org.springframework.orm.hibernate4.HibernateTransactionManager Triggering afterCommit synchronization

org.springframework.orm.hibernate4.HibernateTransactionManager Triggering afterCompletion synchronization

org.springframework.transaction.support.TransactionSynchronizationManager Clearing transaction synchronization

……

org.springframework.orm.hibernate4.HibernateTransactionManager Closing Hibernate Session …… after transaction  --關閉 a Session

此處我們可以看到b方法的事務起作用了。

以上方式是解決目標物件內部方法自我呼叫並實施事務的最簡單的解決方案。

4、實現原理分析

4.1、在進入代理物件之後通過AopContext.serCurrentProxy(proxy)暴露當前代理物件到ThreadLocal,並儲存上次ThreadLocal繫結的代理物件為oldProxy;

4.2、接下來我們可以通過 AopContext.currentProxy() 獲取當前代理物件;

4.3、在退出代理物件之前要重新將ThreadLocal繫結的代理物件設定為上一次的代理物件,即AopContext.serCurrentProxy(oldProxy)。

有些人不喜歡這種方式,說通過ThreadLocal暴露有效能問題,其實這個不需要考慮,因為事務相關的(SessionConnection)內部也是通過SessionHolderConnectionHolder暴露到ThreadLocal實現的。

不過自我呼叫這種場景確實只有很少情況遇到,因此不用這種方式我們也可以通過如下方式實現。

3.2、通過初始化方法在目標物件中注入代理物件

Java程式碼  收藏程式碼
  1. @Service  
  2. public class AServiceImpl3 implements AService{  
  3.     @Autowired  //①  注入上下文  
  4.     private ApplicationContext context;  
  5.     private AService proxySelf; //②  表示代理物件,不是目標物件  
  6.     @PostConstruct  //③ 初始化方法  
  7.     private void setSelf() {  
  8.         //從上下文獲取代理物件(如果通過proxtSelf=this是不對的,this是目標物件)  
  9.         //此種方法不適合於prototype Bean,因為每次getBean返回一個新的Bean  
  10.         proxySelf = context.getBean(AService.class);   
  11.     }  
  12.     @Transactional(propagation = Propagation.REQUIRED)  
  13.     public void a() {  
  14.        proxySelf.b(); //④ 呼叫代理物件的方法 這樣可以執行事務切面  
  15.     }  
  16.     @Transactional(propagation = Propagation.REQUIRES_NEW)  
  17.     public void b() {  
  18.     }  
  19. }  

此處日誌就不分析,和3.1類似。此種方式不是很靈活,所有需要自我呼叫的實現類必須重複實現程式碼。

BeanPostProcessor 的介紹和使用敬請等待我的下一篇分析帖。

一、定義BeanPostProcessor 需要使用的標識介面

Java程式碼  收藏程式碼
  1. public interface BeanSelfAware {  
  2.     void setSelf(Object proxyBean);  
  3. }  

 即我們自定義的BeanPostProcessor (InjectBeanSelfProcessor)如果發現我們的Bean是實現了該標識介面就呼叫setSelf注入代理物件。

二、Bean實現

Java程式碼  收藏程式碼
  1. @Service  
  2. public class AServiceImpl4 implements AService, BeanSelfAware {//此處省略介面定義  
  3.     private AService proxySelf;  
  4.     public void setSelf(Object proxyBean) { //通過InjectBeanSelfProcessor注入自己(目標物件)的AOP代理物件  
  5.         this.proxySelf = (AService) proxyBean;  
  6.     }  
  7.     @Transactional(propagation = Propagation.REQUIRED)  
  8.     public void a() {  
  9.         proxySelf.b();//呼叫代理物件的方法 這樣可以執行事務切面  
  10.     }  
  11.     @Transactional(propagation = Propagation.REQUIRES_NEW)  
  12.     public void b() {  
  13.     }  
  14. }   

實現BeanSelfAware標識介面的setSelf將代理物件注入,並且通過“proxySelf.b()”這樣可以實施b方法的事務定義。

三、InjectBeanSelfProcessor實現

Java程式碼  收藏程式碼
  1. @Component  
  2. public class InjectBeanSelfProcessor implements BeanPostProcessor {  
  3.     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {  
  4.         return bean;  
  5.     }  
  6.     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  
  7.         if(bean instanceof BeanSelfAware) {//如果Bean實現了BeanSelfAware標識介面,就將代理物件注入  
  8.             ((BeanSelfAware) bean).setSelf(bean); //即使是prototype Bean也可以使用此種方式  
  9.         }  
  10.         return bean;  
  11.     }  
  12. }  

postProcessAfterInitialization根據目標物件是否實現BeanSelfAware標識介面,通過setSelf(bean)將代理物件(bean)注入到目標物件中,從而可以完成目標物件內部的自我呼叫。

關於BeanPostProcessor的執行流程等請一定參考我的這篇帖子,否則無法繼續往下執行。

四、InjectBeanSelfProcessor的問題

(1、場景:通過InjectBeanSelfProcessor進行注入代理物件且迴圈依賴場景下會產生前者無法通過setSelf設定代理物件的問題。 迴圈依賴是應該避免的,但是實際工作中不可避免會有人使用這種注入,畢竟沒有強制性。

(2、用例

(2.1、定義BeanPostProcessor 需要使用的標識介面

和3.1中一樣此處不再重複。

(2.2、Bean實現

Java程式碼  收藏程式碼
  1. @Service  
  2. public class AServiceImpl implements AService, BeanSelfAware {//此處省略Aservice介面定義  
  3.     @Autowired  
  4.     private BService bService;   //①  通過@Autowired方式注入BService  
  5.     private AService self;       //②  注入自己的AOP代理物件  
  6.     public void setSelf(Object proxyBean) {  
  7.         this.self = (AService) proxyBean;  //③ 通過InjectBeanSelfProcessor注入自己(目標物件)的AOP代理物件  
  8.         System.out.println("AService=="+ AopUtils.isAopProxy(this.self)); //如果輸出true標識AOP代理物件注入成功  
  9.     }  
  10.     @Transactional(propagation = Propagation.REQUIRED)  
  11.     public void a() {  
  12.         self.b();  
  13.     }  
  14.     @Transactional(propagation = Propagation.REQUIRES_NEW)  
  15.     public void b() {  
  16.     }  
  17. }  
Java程式碼  收藏程式碼
  1. @Service  
  2. public class BServiceImpl implements BService, BeanSelfAware {//此處省略Aservice介面定義  
  3.     @Autowired  
  4.     private AService aService;  //①  通過@Autowired方式注入AService  
  5.     private BService self;      //②  注入自己的AOP代理物件  
  6.     public void setSelf(Object proxyBean) {  //③ 通過InjectBeanSelfProcessor注入自己(目標物件)的AOP代理物件  
  7.         this.self = (BService) proxyBean;  
  8.         System.out.println("BService=" + AopUtils.isAopProxy(this.self)); //如果輸出true標識AOP代理物件注入成功  
  9.     }  
  10.     @Transactional(propagation = Propagation.REQUIRED)  
  11.     public void a() {  
  12.         self.b();  
  13.     }  
  14.     @Transactional(propagation = Propagation.REQUIRES_NEW)  
  15.     public void b() {  
  16.     }  
  17. }  

此處A依賴B,B依賴A,即構成迴圈依賴,此處不探討迴圈依賴的設計問題(實際工作應該避免迴圈依賴),只探討為什麼迴圈依賴會出現注入代理物件失敗的問題。

(2.3、InjectBeanSelfProcessor實現

和之前3.3中一樣 此處不再重複。

(2.4、測試用例

Java程式碼  收藏程式碼
  1. @RunWith(value = SpringJUnit4ClassRunner.class)  
  2. @ContextConfiguration(value = {"classpath:spring-config.xml"})  
  3. public class SelfInjectTest {  
  4.     @Autowired  
  5.     AService aService;  
  6.     @Autowired  
  7.     BService bService;  
  8.     @Test  
  9.     public void test() {  
  10.     }  
  11. }  

執行如上測試用例會輸出:

BService=true

AService==false

即BService通過InjectBeanSelfProcessor注入代理物件成功,而AService卻失敗了(實際是注入了目標物件),如下是debug得到的資訊:


 

(2. 5、這是為什麼呢,怎麼在迴圈依賴會出現這種情況?

敬請期待我的下一篇分析帖。

3.4、改進版的InjectBeanSelfProcessor的解決方案

Java程式碼  收藏程式碼
  1. @Component  
  2. public class InjectBeanSelfProcessor2 implements BeanPostProcessor, ApplicationContextAware {  
  3.     private ApplicationContext context;  
  4.     //① 注入ApplicationContext  
  5.     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {  
  6.         this.context = applicationContext;  
  7.     }  
  8.     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  
  9.         if(!(bean instanceof BeanSelfAware)) { //② 如果Bean沒有實現BeanSelfAware標識介面 跳過  
  10.             return bean;  
  11.         }  
  12.         if(AopUtils.isAopProxy(bean)) { //③ 如果當前物件是AOP代理物件,直接注入  
  13.             ((BeanSelfAware) bean).setSelf(bean);  
  14.         } else {  
  15.             //④ 如果當前物件不是AOP代理,則通過context.getBean(beanName)獲取代理物件並注入  
  16.             //此種方式不適合解決prototype Bean的代理物件注入  
  17.             ((BeanSelfAware)bean).setSelf(context.getBean(beanName));  
  18.         }  
  19.         return bean;  
  20.     }  
  21.     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {  
  22.         return bean;  
  23.     }  
  24. }  

5、總結

縱觀其上:

【3.1 通過ThreadLocal暴露Aop代理物件】適合解決所有場景(不管是singleton Bean還是prototype Bean)的AOP代理獲取問題(即能解決目標物件的自我呼叫問題);

【3.2 通過初始化方法在目標物件中注入代理物件】 和【3.4 改進版的InjectBeanSelfProcessor的解決方案】能解決普通(無迴圈依賴)的AOP代理物件注入問題,而且也能解決【3.3】中提到的迴圈依賴(應該是singleton之間的迴圈依賴)造成的目標物件無法注入AOP代理物件問題,但該解決方案不適合解決迴圈依賴中包含prototype Bean的自我呼叫問題;

【3.3 通過BeanPostProcessor 在目標物件中注入代理物件】:只能解決 普通(無迴圈依賴)的 的Bean注入AOP代理無法解決迴圈依賴的AOP代理物件注入問題,即無法解決目標物件的自我呼叫問題。

jingnianshilongnian 寫道
spring允許的迴圈依賴(只考慮單例和原型Bean):
A----B
B----A
只有在A和B都不為原型是允許的,即如果A和B都是prototype則會報錯(無法進行原型Bean的迴圈依賴)。
A(單例)---B(單例) 或 A(原型)---B(單例) 這是可以的,但 A(原型)---B(原型)或 A(原型)---B(單例Lazy)【且context.getBean("A")】時 這是不允許的。

一、A(原型)---B(原型) A(原型)---B(單例Lazy)【且context.getBean("A")】 會報:
Error creating bean with name 'BServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.sishuok.issue.AService com.sishuok.issue.impl.BServiceImpl.aService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'AServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.sishuok.issue.BService com.sishuok.issue.impl.AServiceImpl.bService; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'BServiceImpl': Requested bean is currently in creation: [color=red]Is there an unresolvable circular reference[/color]?

二、A(原型)---B(單例) 和 A(單例)---B(單例)
這種方式 使用我的 【3.3 通過BeanPostProcessor 在目標物件中注入代理物件】 是沒有問題的。

因此【 3.4 改進版的InjectBeanSelfProcessor的解決方案 】 可以作為最後的解決方案。

相關推薦

spring宣告事務 一類方法呼叫事務失效

前些日子一朋友在需要在目標物件中進行自我呼叫,且需要實施相應的事務定義,且網上的一種通過BeanPostProcessor的解決方案是存在問題的。因此專門寫此篇帖子分析why。 1、預備知識 使用AOP 代理後的方法呼叫執行流程,如圖所示 也就是說我們首先呼叫的是AOP代理物件而不是目標物件,首先

第十二講:12,spring宣告事務管理-註解

1,複製專案spring404 ,改名spring404-3。修改BankServiceImpl類,添加註解,package com.cruise.service.impl;import org.springframework.transaction.annotation.Tra

第十一講:11.spring宣告事務管理-xml方式

1,複製專案spring404 ,改名spring404-2,修改BankServiceImpl類,刪除宣告式事務的程式碼。宣告式事務管理的方式缺點是,事務程式碼嚴重嵌入邏輯程式碼中 package com.cruise.service.impl; import org.springframewor

spring宣告事務管理方式( 基於tx和aop名字空間的xml配置[email&#

轉自:https://www.cnblogs.com/niceyoo/p/8732891.html 1. 宣告式事務管理分類 宣告式事務管理也有兩種常用的方式, 一種是基於tx和aop名字空間的xml配置檔案,另一種就是基於@Transactional註解。 顯然基於註解的方式更簡單

Spring宣告事務(待更新)

四大特性:ACID 原子性:一個事務必須視為一個不可分割的最小工作單元,一個事務要麼全部完成,要麼全部失敗回滾,不可能只執行其中的一部分操作 一致性:事務執行的結果必須使資料庫從一個一致性狀態轉換到另一個一致性狀態,事務必須使資料庫始終保持一致性狀態 隔離性isolat

Spring 宣告事務

事務傳播機制 propagation:事務傳播機制有如下幾種: REQUIRED:預設值,表示如果存在一個事務,則支援當前事務;如果沒有事務,則開啟一個新事務。 REQUIRES_NEW:表示總是開啟一個新的事務,如果一個事務已經存在,則將這個存在的事務掛起,開啟新事務

spring系列】之14:spring宣告事務實現原理剖析

通過上一節事務環境搭建,我們知道,在搭建的5個步驟中,有兩個是spring為我們提供底層去稍作配置,然後使用的, 這兩個操作涉及的便是: @EnableTransactionManagement PlatformTransactionManager 其中,Platfor

Spring 宣告事務原始碼分析

Spring 的宣告式事務實現方式主要有2種,一種為通過使用Spring的< tx:advice >定義事務通知與AOP相關配置實現,另為一種通過@Transactional實現事務管理實現,個人認為本質上其實都一樣,就是用定義的註解或者配置資訊將目

Spring宣告事務@Transactional傳播行為

在@Transactional註解中,可以propagation屬性用來配置事務傳播,支援7種不同的傳播機制: REQUIRED:業務方法需要在一個事務中執行,如果方法執行時,已處在一個事務中,那麼就加入該事務,否則自己建立一個新的事務。這是spring預設

spring 宣告事務配置,丟擲runtimeException異常不回滾

預設spring只在發生未被捕獲的runtimeexcetpion時才回滾。 最容易解決的辦法:程式碼級控制:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); try{ ..

spring 宣告事務傳播特性詳解(包括異常回滾舉例)

1:Service介面實現 public interface IProcessBusiService {       //事務1@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW

Spring事務方法呼叫自身事務 增強的三種方式

ServiceA.java檔案:     檢視Spring Tx的相關日誌:  可以看到只建立了一個事物ServiceA.service方法的事務,但是callSelf方法卻沒有被事務增強;       &nbs

Spring宣告事務管理、事務的傳播行為xml配置

 1. <tx:method name="insert*" propagation="REQUIRED" />中name的值是ServiceImpl中各個要加入事物管理的方法的方法名。 <!-- 事務管理: Spring宣告式事務管理 。

spring宣告事務管理:基於註解的方式

1)在spring.xml中配置事務管理器DataSourceTransactionManager,<bean id="txManager" class="org.springframework.

Spring宣告事務管理及事務巢狀

一>  事務配置 Spring動態代理的一個重要特徵是,它是針對介面的,所以我們的dao要通過動態代理來讓spring接管事務,就必須在dao前面抽象出一個介面,當然如果沒有這樣的介面,那麼spring會使用CGLIB來解決問題。     一般地,使用Spri

mysql事務管理及spring宣告事務中主動異常丟擲使資料庫回滾

原文: http://www.cnblogs.com/wanglonghai/p/4866512.html   mysql的引擎常用的有兩個,一個MyISAM,另一個是InnoDB,mysql預設的為MyISAM,而InnoDB才是支援事務的。所以一般需要修改下

Spring宣告事務注意點,以及不生效情況

情況1: class XxxService{ public void methodA(){ methodB() } @Transactional

2.1 Spring宣告事務的實現方式選擇(JDK動態代理與cglib)

1、簡介Spring宣告式事務的具體實現方式是動態決定的,與具體配置、以及事務代理物件是否實現介面等有關。2、使用JDK動態代理的情況在滿足下面兩個條件時,Spring會選擇JDK動態代理作為宣告式事務

Spring宣告事務管理原始碼解析

核心介面 1. PlatformTransactionManager:事務管理器頂級介面:各持久化框架要想接入Spring的事務管理,必須自行提供該介面實現 2. TransactionDefinition:事務的屬性頂級介面:其實現類封裝事務隔離級別、

Spring宣告事務不回滾問題

在使用Spring事務的時候我們經常使用註解@Transactional來宣告事務,下面讓我們來看一下Spring事務存在的坑。內部呼叫方法不會走代理方式呼叫,而是類內部的函式呼叫,有事務註解也不會開啟事務,但是當A有事務呼叫B時,B會加入A事務中,使之為同一事務。解決方法: