Spring Transaction
- @EnableTransactionManagement
- AutoProxyRegistrar
- ProxyTransactionManagementConfiguration
-
- 給容器中注冊事務增強器transactionAdvisor
- 事務攔截器transactionInterceptor
- 事務隔離級别
- 事務傳播行為
@EnableTransactionManagement
利用TransactionManagementConfigurationSelector給容器中會導入元件
- AutoProxyRegistrar
- ProxyTransactionManagementConfiguration
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
//導入兩個元件
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
AutoProxyRegistrar
- 給容器中注冊一個 InfrastructureAdvisorAutoProxyCreator 元件;
- 利用後置處理器機制在對象建立以後,包裝對象,傳回一個代理對象(增強器),代理對象執行方法利用攔截器鍊進行調用;
ProxyTransactionManagementConfiguration
ProxyTransactionManagementConfiguration是個@Configuration
給容器中注冊事務增強器transactionAdvisor
- 事務增強器要用事務注解的資訊,AnnotationTransactionAttributeSource解析事務注解
事務攔截器transactionInterceptor
- TransactionInterceptor: 儲存了事務屬性資訊,事務管理器;
-
TransactionInterceptor是一個 MethodInterceptor;
在目标方法執行的時候,執行攔截器鍊;
隻有事務攔截器:
- 先擷取事務相關的屬性
-
再擷取PlatformTransactionManager,如果事先沒有添加指定任何transactionmanger
最終會從容器中按照類型擷取一個PlatformTransactionManager;
-
執行目标方法
如果異常,擷取到事務管理器,利用事務管理復原操作;
如果正常,利用事務管理器,送出事務
事務隔離級别
@Transactional(isolation = Isolation.READ_UNCOMMITTED) 讀取未送出資料(會出現髒讀, 不可重複讀),基本不使用
@Transactional(isolation = Isolation.READ_COMMITTED)(SQLSERVER預設) 讀取已送出資料(會出現不可重複讀和幻讀)
@Transactional(isolation = Isolation.REPEATABLE_READ) 可重複讀(會出現幻讀)
@Transactional(isolation = Isolation.SERIALIZABLE) 串行化
事務傳播行為
@Transactional(propagation=Propagation.REQUIRED) 如果有事務, 那麼加入事務, 沒有的話建立一個(預設情況)
@Transactional(propagation=Propagation.NOT_SUPPORTED) 容器不為這個方法開啟事務
@Transactional(propagation=Propagation.REQUIRES_NEW) 不管是否存在事務,都建立一個新的事務,原來的挂起,新的執行完畢,繼續執行老的事務
@Transactional(propagation=Propagation.MANDATORY) 必須在一個已有的事務中執行,否則抛出異常
@Transactional(propagation=Propagation.NEVER) 必須在一個沒有的事務中執行,否則抛出異常(與Propagation.MANDATORY相反)
@Transactional(propagation=Propagation.SUPPORTS) 如果其他bean調用這個方法,在其他bean中聲明事務,那就用事務。如果其他bean沒有聲明事務,那就不用事務