事務是一組原子性的SQL查詢,或者說是一個獨立的工做單元。要麼所有執行,要麼所有不執行。html
①原子性(atomicity)java
一個事務必須被視爲一個不可分割的最小工做單元,整個事務中的全部操做要麼所有提交成功,要麼所有回滾,對於一個事務來講,不可能只執行其中的一部分操做mysql
②一致性(consistency)git
數據庫老是從一個一致性的狀態轉換到另一個一致性的狀態。spring
③隔離性(isolation)sql
一個事務所作的修改在最終提交之前,對其餘事務是不可見的。也就是說多個併發事務之間要相互隔離。數據庫
④持久性(durability)編程
一旦事務提交,則其所作的修改就會永久的保存在數據庫中,接下來即便數據庫系統崩潰了,修改的數據也不會丟失設計模式
①讀未提交(READ UNCOMMITTED)緩存
事務中的修改,即便沒有提交,對其餘事務也是可見的,也就是說事務能夠讀取到未提交的數據,這也被稱爲髒讀。
②讀已提交(READ COMMITTED)
一個事務從開始到提交以前,所作的任何修改對其餘事務都是不可見的,這個級別有時候也叫不可重複讀,由於兩次執行一樣的查詢,可能會獲得不同的結果。
③可重複讀(REPEATABLE READ)
該隔離級別保證了在同一個事務中屢次讀取一樣的記錄的結果是一致的,可是沒法解決另一個幻讀的問題,所謂的幻讀就是指當某個事務在讀取某個範圍內的記錄是,另一個事務又在該範圍內插入了新的記錄,當以前的事務再次讀取該範圍的記錄時就會產生幻行。
④可串行化(SERIALIZABLE)
SERIALIZABLE是最高的隔離級別,經過強制事務的串行執行,避免了前面說的幻讀問題,簡單來講,SERIALIZABLE會在讀取的每一行數據上加上鎖。
public interface PlatformTransactionManager { /** * 獲取事務 */ TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; /** * 提交 */ void commit(TransactionStatus status) throws TransactionException; /** * 回滾 */ void rollback(TransactionStatus status) throws TransactionException; }
public interface TransactionDefinition { /** * Support a current transaction; create a new one if none exists. 支持當前事物,若當前沒有事物就建立一個事物 */ int PROPAGATION_REQUIRED = 0; /** * Support a current transaction; execute non-transactionally if none exists. 若是當前存在事務,則加入該事務;若是當前沒有事務,則以非事務的方式運行 */ int PROPAGATION_SUPPORTS = 1; /** * Support a current transaction; throw an exception if no current transaction exists. 若是當前存在事務,則加入該事務;若是當前沒有事務,則拋出異常 */ int PROPAGATION_MANDATORY = 2; /** * Create a new transaction, suspending the current transaction if one exists.建立一個新的事務,若是當前存在事務,則把當前事務掛起 */ int PROPAGATION_REQUIRES_NEW = 3; /** * Do not support a current transaction; rather always execute non-transactionally.以非事務方式運行,若是當前存在事務,則把當前事務掛起 */ int PROPAGATION_NOT_SUPPORTED = 4; /** * Do not support a current transaction; throw an exception if a current transaction exists. 以非事務方式運行,若是當前存在事務,則拋出異常 */ int PROPAGATION_NEVER = 5; /** * Execute within a nested transaction if a current transaction exists.若是外層存在事務,就以嵌套事務運行,被嵌套的事務能夠獨立於外層事務進行提交或者回滾(保存點), 若是外層不存在事務,行爲跟PROPAGATION_REQUIRES_NEW */ int PROPAGATION_NESTED = 6; /** * Use the default isolation level of the underlying datastore. 使用數據庫默認的隔離級別
*/ int ISOLATION_DEFAULT = -1; /** * 讀未提交
*/ int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED; /** * 讀已提交
*/ int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED; /** * 可重複讀*/ int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ; /** * 可串行化
*/ int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE; /** * 使用默認的超時時間 */ int TIMEOUT_DEFAULT = -1; /** * 獲取事物的傳播行爲
*/ int getPropagationBehavior(); /** * 獲取事物的隔離級別
*/ int getIsolationLevel(); /** * 獲取事物的超時時間
*/ int getTimeout(); /** * 是否爲只讀事物
*/ boolean isReadOnly(); /** * 獲取當前事物的名稱
*/ String getName(); }
public interface TransactionStatus extends SavepointManager, Flushable { /** * 是否爲新事務 */ boolean isNewTransaction(); /** * 是否有保存點*/ boolean hasSavepoint(); /** * 設置爲只回滾*/ void setRollbackOnly(); /** * 是否爲只回滾 */ boolean isRollbackOnly(); /** * 講會話刷新到數據庫中 */ @Override void flush(); /** * 當前事務是否已經完成*/ boolean isCompleted(); }
@EnableTransactionManagement @ComponentScan(basePackages = {"com.toby"}) public class TransactionConfig { @Bean public DataSource dataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setUsername("root"); dataSource.setPassword("123qwe"); dataSource.setUrl("jdbc:mysql://localhost:3306/demo_db?useUnicode=true&characterEncoding=utf-8&useSSL=false"); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); return dataSource; } @Bean public JdbcTemplate jdbcTemplate(DataSource dataSource) { return new JdbcTemplate(dataSource); } @Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } }
源碼解析跟Spring系列(五):Spring AOP源碼解析中的@EnableAspectJAutoProxy註解同樣,能夠參考下。主要給Spring容器加入以下組件:
該接口有2個方法postProcessBeforeInstantiation和postProcessAfterInstantiation,其中實例化以前會執行postProcess BeforeInstantiation方法:
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { //構建咱們的緩存key Object cacheKey = getCacheKey(beanClass, beanName); if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { //若是被解析過直接返回 if (this.advisedBeans.containsKey(cacheKey)) { return null; } /** * 判斷是否是基礎的bean * 判斷是否是應該跳過 (此處Spring Aop解析直接解析出咱們的切面信息(而且把咱們的切面信息進行緩存),
* 而事務在這裏是不會解析的,爲何?緣由事務的話已經把事務攔截器經過@Bean,而Aop的須要尋找) */ if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { if (StringUtils.hasLength(beanName)) { this.targetSourcedBeans.add(beanName); } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } return null; }
該接口有2個方法postProcessBeforeInitialization和postProcessAfterInitialization,其中組件初始化以後會執行postProcessAfterInitialization(該方法建立Aop和事務的代理對象)方法:
/** * 在該後置方法中 咱們的事務和aop的代理對象都是在這生成的 * @param bean bean實例 * @param beanName bean的名稱 * @return * @throws BeansException */ @Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException { if (bean != null) { //獲取緩存key Object cacheKey = getCacheKey(bean.getClass(), beanName); if (this.earlyProxyReferences.remove(cacheKey) != bean) { //若是有必要就代理 return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
進去wrapIfNecessary(bean, beanName, cacheKey)方法:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { //已經被處理過 if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } //不須要加強的 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } //是否是基礎的bean 是否是須要跳過的 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } //若是有匹配的通知,就建立代理對象 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); //若是不爲空,表述須要代理 if (specificInterceptors != DO_NOT_PROXY) { //設置當前的對象已處理 this.advisedBeans.put(cacheKey, Boolean.TRUE); //建立咱們的真正的代理對象 Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); //加入到緩存 this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }
進入getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null)方法:
protected Object[] getAdvicesAndAdvisorsForBean( Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) { /** * 找合適的加強器對象 */ List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); //若合適的通知器爲空 if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); }
進入findEligibleAdvisors(beanClass, beanName)方法:
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { //找到Spring IoC容器中全部的候選通知 包括Aop的和事務的 List<Advisor> candidateAdvisors = findCandidateAdvisors(); //判斷找到的通知能不能做用到當前的類上 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); //對咱們的advisor進行排序 if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
① 進入findCandidateAdvisors()方法,經過加強器檢索器檢索加強器:
進入findAdvisorBeans()方法:
public List<Advisor> findAdvisorBeans() { String[] advisorNames = this.cachedAdvisorBeanNames; if (advisorNames == null) { /** * 去容器中獲取到實現了Advisor接口的實現類 咱們的事務註解@EnableTransactionManagement導入了一個叫ProxyTransactionManagementConfiguration配置類 * 而在這個配置類中配置了: * @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) * @Role(BeanDefinition.ROLE_INFRASTRUCTURE) * public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(); * 而後把他的名字獲取出來保存到 本類的屬性變量cachedAdvisorBeanNames中 */ advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Advisor.class, true, false); this.cachedAdvisorBeanNames = advisorNames; } //若在容器中沒有找到,直接返回一個空的集合 if (advisorNames.length == 0) { return new ArrayList<>(); } List<Advisor> advisors = new ArrayList<>(); //容器中找到了咱們事務配置的BeanFactoryTransactionAttributeSourceAdvisor for (String name : advisorNames) { //判斷他是否是一個合適的 if (isEligibleBean(name)) { //BeanFactoryTransactionAttributeSourceAdvisor是否是正在建立的Bean if (this.beanFactory.isCurrentlyInCreation(name)) { if (logger.isDebugEnabled()) { logger.debug("Skipping currently created advisor '" + name + "'"); } } //不是的話 else { try { //顯示的調用getBean方法方法建立咱們的BeanFactoryTransactionAttributeSourceAdvisor返回去 advisors.add(this.beanFactory.getBean(name, Advisor.class)); } catch (BeanCreationException ex) { Throwable rootCause = ex.getMostSpecificCause(); if (rootCause instanceof BeanCurrentlyInCreationException) { BeanCreationException bce = (BeanCreationException) rootCause; String bceBeanName = bce.getBeanName(); if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) { if (logger.isDebugEnabled()) { logger.debug("Skipping advisor '" + name + "' with dependency on currently created bean: " + ex.getMessage()); } // Ignore: indicates a reference back to the bean we're trying to advise. // We want to find advisors other than the currently created bean itself. continue; } } throw ex; } } } } return advisors; }
進入到isEligibleBean(name)方法:
進入isEligibleAdvisorBean(beanName)方法:
protected boolean isEligibleAdvisorBean(String beanName) { /** * 容器中包含了這個Bean定義,而且Bean定義的角色爲BeanDefinition.ROLE_INFRASTRUCTURE */ return (this.beanFactory != null && this.beanFactory.containsBeanDefinition(beanName) && this.beanFactory.getBeanDefinition(beanName).getRole() == BeanDefinition.ROLE_INFRASTRUCTURE); }
若是是合適的就保存在advisors中並返回;至此findCandidateAdvisors()執行完畢!!!
進入到AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass)方法:
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { //若候選的加強器集合爲空直接返回 if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } //定義一個合適的加強器集合對象 List<Advisor> eligibleAdvisors = new ArrayList<>(); //循環咱們候選的加強器對象 for (Advisor candidate : candidateAdvisors) { //判斷咱們的加強器對象是否是實現了IntroductionAdvisor (很明顯咱們事務的沒有實現 因此不會走下面的邏輯) if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } //不爲空 boolean hasIntroductions = !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { //判斷咱們的加強器對象是否是實現了IntroductionAdvisor (很明顯咱們事務的沒有實現 因此不會走下面的邏輯) if (candidate instanceof IntroductionAdvisor) { //在上面已經處理過 ,不須要處理 continue; } /** * 真正的判斷加強器是否合適當前類 */ if (canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; }
真正的判斷加強器是否合適當前類,canApply(candidate, clazz, hasIntroductions)方法:
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) { //判斷咱們的加強器 IntroductionAdvisor if (advisor instanceof IntroductionAdvisor) { return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass); } //判斷咱們事務的加強器BeanFactoryTransactionAttributeSourceAdvisor是否實現了PointcutAdvisor else if (advisor instanceof PointcutAdvisor) { //轉爲PointcutAdvisor類型 PointcutAdvisor pca = (PointcutAdvisor) advisor; //找到真正能用的加強器 return canApply(pca.getPointcut(), targetClass, hasIntroductions); } else { // It doesn't have a pointcut so we assume it applies. return true; } }
找到真正能用的加強器,canApply(pca.getPointcut(), targetClass, hasIntroductions)方法:
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) { Assert.notNull(pc, "Pointcut must not be null"); if (!pc.getClassFilter().matches(targetClass)) { return false; } /** * 經過切點獲取到一個方法匹配器對象 */ MethodMatcher methodMatcher = pc.getMethodMatcher(); if (methodMatcher == MethodMatcher.TRUE) { // No need to iterate the methods if we're matching any method anyway... return true; } //判斷匹配器是否是IntroductionAwareMethodMatcher IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; } //建立一個集合用於保存targetClass的class對象 Set<Class<?>> classes = new LinkedHashSet<>(); //判斷當前class是否是代理的class對象 if (!Proxy.isProxyClass(targetClass)) { //加入到集合中去 classes.add(ClassUtils.getUserClass(targetClass)); } //獲取到targetClass所實現的接口的class對象,而後加入到集合中 classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); //循環全部的class對象 for (Class<?> clazz : classes) { //經過class獲取到全部的方法 Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz); //循環咱們的方法 for (Method method : methods) { //經過methodMatcher.matches來匹配咱們的方法 if (introductionAwareMethodMatcher != null ? introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) : //經過方法匹配器進行匹配 methodMatcher.matches(method, targetClass)) { return true; } } } return false; }
進入methodMatcher.matches(method, targetClass)方法:
public boolean matches(Method method, @Nullable Class<?> targetClass) { if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) { return false; } /** * 獲取咱們@EnableTransactionManagement註解爲咱們容器中導入的ProxyTransactionManagementConfiguration * 配置類中的TransactionAttributeSource對象 */ TransactionAttributeSource tas = getTransactionAttributeSource(); //若事務屬性原爲null或者 解析出來的事務註解屬性不爲空 表示方法匹配 return (tas == null || tas.getTransactionAttribute(method, targetClass) != null); }
進入到獲取事務註解屬性tas.getTransactionAttribute(method, targetClass)方法:
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) { //判斷method所在的class 是否是Object類型 if (method.getDeclaringClass() == Object.class) { return null; } //構建咱們的緩存key Object cacheKey = getCacheKey(method, targetClass); //先去咱們的緩存中獲取 TransactionAttribute cached = this.attributeCache.get(cacheKey); //緩存中不爲空 if (cached != null) { //判斷緩存中的對象是否是空事務屬性的對象 if (cached == NULL_TRANSACTION_ATTRIBUTE) { return null; } else { return cached; } } else { //查找咱們的事務註解 TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass); //若解析出來的事務註解屬性爲空 if (txAttr == null) { //往緩存中存放空事務註解屬性 this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE); } else { //咱們執行方法的描述符 包名+類名+方法名 String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass); //把方法描述設置到事務屬性上去 if (txAttr instanceof DefaultTransactionAttribute) { ((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification); } if (logger.isDebugEnabled()) { logger.debug("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr); } //加入到緩存 this.attributeCache.put(cacheKey, txAttr); } return txAttr; } }
進入查找咱們的事務註解,computeTransactionAttribute(method, targetClass)方法:
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) { //判斷咱們的事務方法上的修飾符是否是public的 if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) { return null; } // The method may be on an interface, but we need attributes from the target class. // If the target class is null, the method will be unchanged. Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass); //第一:先去目標對象的方法上去找咱們的事務註解 TransactionAttribute txAttr = findTransactionAttribute(specificMethod); if (txAttr != null) { return txAttr; } //第二:去目標對象上找事務註解 txAttr = findTransactionAttribute(specificMethod.getDeclaringClass()); if (txAttr != null && ClassUtils.isUserLevelMethod(method)) { return txAttr; } if (specificMethod != method) { //第三:去咱們的實現類的接口上的方法去找事務註解 txAttr = findTransactionAttribute(method); if (txAttr != null) { return txAttr; } //第四:去咱們的實現類的接口上去找事務註解 txAttr = findTransactionAttribute(method.getDeclaringClass()); if (txAttr != null && ClassUtils.isUserLevelMethod(method)) { return txAttr; } } return null; }
進入到找@Transactional註解,findTransactionAttribute(specificMethod)方法:
進入determineTransactionAttribute(method)方法:
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) { //獲取咱們的註解解析器 for (TransactionAnnotationParser annotationParser : this.annotationParsers) { //經過註解解析器去解析咱們的元素(方法或者類)上的註解 TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element); if (attr != null) { return attr; } } return null; }
進入annotationParser.parseTransactionAnnotation(element)方法:
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) { //從element對象中獲取@Transactional註解 而後把註解屬性封裝到了AnnotationAttributes AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes( element, Transactional.class, false, false); if (attributes != null) { //解析出真正的事務屬性對象 return parseTransactionAnnotation(attributes); } else { return null; } }
進入到解析出真正的事務屬性對象,parseTransactionAnnotation(attributes)方法:
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) { //建立一個基礎規則的事務屬性對象 RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute(); //解析@Transactionl上的傳播行爲 Propagation propagation = attributes.getEnum("propagation"); rbta.setPropagationBehavior(propagation.value()); //解析@Transactionl上的隔離級別 Isolation isolation = attributes.getEnum("isolation"); rbta.setIsolationLevel(isolation.value()); //解析@Transactionl上的事務超時事件 rbta.setTimeout(attributes.getNumber("timeout").intValue()); rbta.setReadOnly(attributes.getBoolean("readOnly")); //解析@Transactionl上的事務管理器的名稱 rbta.setQualifier(attributes.getString("value")); //解析針對哪一種異常回滾 List<RollbackRuleAttribute> rollbackRules = new ArrayList<>(); for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) { rollbackRules.add(new RollbackRuleAttribute(rbRule)); } //對哪一種異常進行回滾 for (String rbRule : attributes.getStringArray("rollbackForClassName")) { rollbackRules.add(new RollbackRuleAttribute(rbRule)); } //對哪一種異常不回滾 for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) { rollbackRules.add(new NoRollbackRuleAttribute(rbRule)); } //對哪一種類型不回滾 for (String rbRule : attributes.getStringArray("noRollbackForClassName")) { rollbackRules.add(new NoRollbackRuleAttribute(rbRule)); } rbta.setRollbackRules(rollbackRules); return rbta; }
至此computeTransactionAttribute(method, targetClass)方法執行完畢!!!
而後把咱們執行方法的描述符設置到TransactionAttribute事務屬性中,表示該方法須要執行Spring事務,並把事務註解屬性加入到緩存attributeCache中,至此獲取事務註解屬性tas.getTransactionAttribute完畢!!!
若是canApply方法返回true表示找到真正能用的加強器了,而後就把合適的加強器加入到eligibleAdvisors中:
至此findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName)執行完畢!!!
③ extendAdvisors(eligibleAdvisors) 擴展加強器
④ sortAdvisors(eligibleAdvisors) 排序
其中③,④ 略 具體參考Spring系列(五):Spring AOP源碼解析,其實事務找加強器相對Aop簡單不少,到此findEligibleAdvisors(beanClass, beanName)執行完畢!!!
到此Spring事務建立代理對象完畢!!!
其實就是調用org.springframework.aop.framework.JdkDynamicAopProxy#invoke
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object oldProxy = null; boolean setProxyContext = false; //獲取到咱們的目標對象 TargetSource targetSource = this.advised.targetSource; Object target = null; try { //如果equals方法不須要代理 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } //如果hashCode方法不須要代理 else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } //如果DecoratingProxy也不要攔截器執行 else if (method.getDeclaringClass() == DecoratingProxy.class) { // There is only getDecoratedClass() declared -> dispatch to proxy config. return AopProxyUtils.ultimateTargetClass(this.advised); } else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { // Service invocations on ProxyConfig with the proxy config... return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; /** * 這個配置是暴露咱們的代理對象到線程變量中,須要搭配@EnableAspectJAutoProxy(exposeProxy = true)一塊兒使用 * 好比在目標對象方法中再次獲取代理對象可使用這個AopContext.currentProxy() * 還有的就是事務方法調用事務方法的時候也是用到這個 */ if (this.advised.exposeProxy) { //把咱們的代理對象暴露到線程變量中 oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } //獲取咱們的目標對象 target = targetSource.getTarget(); //獲取咱們目標對象的class Class<?> targetClass = (target != null ? target.getClass() : null); //把aop的advisor轉化爲攔截器鏈 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); //若是攔截器鏈爲空 if (chain.isEmpty()) { //經過反射直接調用執行 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { //建立一個方法調用對象 MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); //調用執行 retVal = invocation.proceed(); } // Massage return value if necessary. Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // Special case: it returned "this" and the return type of the method // is type-compatible. Note that we can't help if the target sets // a reference to itself in another returned object. retVal = proxy; } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { throw new AopInvocationException( "Null return value from advice does not match primitive return type for: " + method); } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }
進入到invocation.proceed()方法,該方法的調用用到了遞歸和責任鏈設計模式:
public Object proceed() throws Throwable { //從-1開始,下標=攔截器的長度-1的條件知足表示執行到了最後一個攔截器的時候,此時執行目標方法 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } //獲取第一個方法攔截器使用的是前++ Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // Evaluate dynamic method matcher here: static part will already have // been evaluated and found to match. InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { return dm.interceptor.invoke(this); } else { // Dynamic matching failed. // Skip this interceptor and invoke the next in the chain. return proceed(); } } else { return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
進入到((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this)方法:
public Object invoke(MethodInvocation invocation) throws Throwable { //獲取咱們的代理對象的class屬性 Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); /** * 以事務的方式調用目標方法 * 在這埋了一個鉤子函數 用來回調目標方法的 */ return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed); }
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, final InvocationCallback invocation) throws Throwable { //獲取咱們的事務屬源對象 TransactionAttributeSource tas = getTransactionAttributeSource(); //經過事務屬性源對象獲取到咱們的事務屬性信息 final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null); //獲取咱們配置的事務管理器對象 final PlatformTransactionManager tm = determineTransactionManager(txAttr); //從tx屬性對象中獲取出標註了@Transactionl的方法描述符 final String joinpointIdentification = methodIdentification(method, targetClass, txAttr); //處理聲明式事務 if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { //有沒有必要建立事務 TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal; try { //調用鉤子函數進行回調目標方法 retVal = invocation.proceedWithInvocation(); } catch (Throwable ex) { //拋出異常進行回滾處理 completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { //清空咱們的線程變量中transactionInfo的值 cleanupTransactionInfo(txInfo); } //提交事務 commitTransactionAfterReturning(txInfo); return retVal; } //編程式事務 else { final ThrowableHolder throwableHolder = new ThrowableHolder(); // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in. try { Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> { TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); try { return invocation.proceedWithInvocation(); } catch (Throwable ex) { if (txAttr.rollbackOn(ex)) { // A RuntimeException: will lead to a rollback. if (ex instanceof RuntimeException) { throw (RuntimeException) ex; } else { throw new ThrowableHolderException(ex); } } else { // A normal return value: will lead to a commit. throwableHolder.throwable = ex; return null; } } finally { cleanupTransactionInfo(txInfo); } }); // Check result state: It might indicate a Throwable to rethrow. if (throwableHolder.throwable != null) { throw throwableHolder.throwable; } return result; } catch (ThrowableHolderException ex) { throw ex.getCause(); } catch (TransactionSystemException ex2) { if (throwableHolder.throwable != null) { logger.error("Application exception overridden by commit exception", throwableHolder.throwable); ex2.initApplicationException(throwableHolder.throwable); } throw ex2; } catch (Throwable ex2) { if (throwableHolder.throwable != null) { logger.error("Application exception overridden by commit exception", throwableHolder.throwable); } throw ex2; } } }
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm, @Nullable TransactionAttribute txAttr, final String joinpointIdentification) { // 把咱們的方法描述符做爲一個事務名稱 if (txAttr != null && txAttr.getName() == null) { txAttr = new DelegatingTransactionAttribute(txAttr) { @Override public String getName() { return joinpointIdentification; } }; } TransactionStatus status = null; if (txAttr != null) { if (tm != null) { //獲取一個事務狀態 status = tm.getTransaction(txAttr); } else { if (logger.isDebugEnabled()) { logger.debug("Skipping transactional joinpoint [" + joinpointIdentification + "] because no transaction manager has been configured"); } } } //把事務狀態和事務屬性等信息封裝成一個TransactionInfo對象 return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); }
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException { //嘗試獲取一個事務對象 Object transaction = doGetTransaction(); // Cache debug flag to avoid repeated checks. boolean debugEnabled = logger.isDebugEnabled(); /** * 判斷從上一個方法傳遞進來的事務屬性是否是爲空 */ if (definition == null) { //爲空的話,執行非事務方法 definition = new DefaultTransactionDefinition(); } /** * 判斷是否是已經存在了事務對象 */ if (isExistingTransaction(transaction)) { //處理存在的事務 return handleExistingTransaction(definition, transaction, debugEnabled); } //檢查事務設置的超時時間 if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) { throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout()); } /** * 若當前的事務屬性式 PROPAGATION_MANDATORY 表示必須運行在事務中,若當前沒有事務就拋出異常 * 因爲isExistingTransaction(transaction)跳過了這裏,說明當前是不存在事務的,那麼就會拋出異常 */ if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) { throw new IllegalTransactionStateException( "No existing transaction found for transaction marked with propagation 'mandatory'"); } /** * PROPAGATION_REQUIRED 當前存在事務就加入到當前的事務,沒有就新開一個 * PROPAGATION_REQUIRES_NEW:新開一個事務,若當前存在事務就掛起當前事務 * PROPAGATION_NESTED: PROPAGATION_NESTED 表示若是當前正有一個事務在運行中,則該方法應該運行在 一個嵌套的事務中, 被嵌套的事務能夠獨立於封裝事務進行提交或者回滾(保存點), 若是封裝事務不存在,行爲就像 PROPAGATION_REQUIRES_NEW */ else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { /** * 掛起當前事務,在這裏爲啥傳入null? * 由於邏輯走到這裏了,通過了上面的isExistingTransaction(transaction) 判斷當前是不存在事務的 * 全部再這裏是掛起當前事務傳遞一個null進去 */ SuspendedResourcesHolder suspendedResources = suspend(null); if (debugEnabled) { logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition); } try { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); //新建立一個事務狀態 DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); //開啓一個新的事物 doBegin(transaction, definition); //把當前的事務信息綁定到線程變量去 prepareSynchronization(status, definition); return status; } catch (RuntimeException | Error ex) { resume(null, suspendedResources); throw ex; } } else { //建立一個空的事務 // Create "empty" transaction: no actual transaction, but potentially synchronization. if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) { logger.warn("Custom isolation level specified but no actual transaction initiated; " + "isolation level will effectively be ignored: " + definition); } boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null); } }
① 進入到doGetTransaction()方法:
protected Object doGetTransaction() { //建立一個數據源事務對象 DataSourceTransactionObject txObject = new DataSourceTransactionObject(); //是否容許當前事務設置保持點 txObject.setSavepointAllowed(isNestedTransactionAllowed()); /** * TransactionSynchronizationManager 事務同步管理器對象(該類中都是局部線程變量) * 用來保存當前事務的信息,咱們第一次從這裏去線程變量中獲取 事務鏈接持有器對象 經過數據源爲key去獲取 * 因爲第一次進來開始事務 咱們的事務同步管理器中沒有被存放.因此此時獲取出來的conHolder爲null */ ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource()); txObject.setConnectionHolder(conHolder, false); //返回事務對象 return txObject; }
② 進入isExistingTransaction(transaction)方法:
protected boolean isExistingTransaction(Object transaction) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; //若第一次進來開始事務,txObject.hasConnectionHolder() 返回的null 那麼表示不存在事務 return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive()); }
③ 因爲事務傳播機制是TransactionDefinition.PROPAGATION_REQUIRED,因此走下面分支
④ 進入掛起事務,suspend(null)方法:
protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException { //判斷當前的線程變量中 有沒有激活的事物,有須要清空線程變量 if (TransactionSynchronizationManager.isSynchronizationActive()) { List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization(); try { Object suspendedResources = null; if (transaction != null) { suspendedResources = doSuspend(transaction); } //獲取已存在的事務的名稱 String name = TransactionSynchronizationManager.getCurrentTransactionName(); //清空線程變量的 TransactionSynchronizationManager.setCurrentTransactionName(null); //獲取出只讀事務的名稱 boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly(); //清空線程變量的 TransactionSynchronizationManager.setCurrentTransactionReadOnly(false); //獲取已存在事務的隔離級別 Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel(); //清空隔離級別 TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null); //獲取激活標誌 boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive(); //清空標記 TransactionSynchronizationManager.setActualTransactionActive(false); //把上訴從線程變量中獲取出來的存在事務屬性封裝爲掛起的事務屬性返回出去 return new SuspendedResourcesHolder( suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive); } catch (RuntimeException | Error ex) { // doSuspend failed - original transaction is still active... doResumeSynchronization(suspendedSynchronizations); throw ex; } } else if (transaction != null) { // Transaction active but no synchronization active. Object suspendedResources = doSuspend(transaction); return new SuspendedResourcesHolder(suspendedResources); } else { // Neither transaction nor synchronization active. return null; } }
⑤ 進入到事務開始,doBegin(transaction, definition)方法:
protected void doBegin(Object transaction, TransactionDefinition definition) { //強制轉化事務對象 DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; Connection con = null; try { //判斷事務對象沒有數據庫鏈接持有器 if (!txObject.hasConnectionHolder() || txObject.getConnectionHolder().isSynchronizedWithTransaction()) { //經過數據源獲取一個數據庫鏈接對象 Connection newCon = obtainDataSource().getConnection(); if (logger.isDebugEnabled()) { logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction"); } //把咱們的數據庫鏈接包裝成一個ConnectionHolder對象 而後設置到咱們的txObject對象中去 txObject.setConnectionHolder(new ConnectionHolder(newCon), true); } //標記當前的鏈接是一個同步事務 txObject.getConnectionHolder().setSynchronizedWithTransaction(true); con = txObject.getConnectionHolder().getConnection(); //爲當前的事務設置隔離級別 Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition); txObject.setPreviousIsolationLevel(previousIsolationLevel); //關閉自動提交 if (con.getAutoCommit()) { txObject.setMustRestoreAutoCommit(true); if (logger.isDebugEnabled()) { logger.debug("Switching JDBC Connection [" + con + "] to manual commit"); } con.setAutoCommit(false); } //判斷事務爲只讀事務 prepareTransactionalConnection(con, definition); //設置事務激活 txObject.getConnectionHolder().setTransactionActive(true); //設置事務超時時間 int timeout = determineTimeout(definition); if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { txObject.getConnectionHolder().setTimeoutInSeconds(timeout); } // 綁定咱們的數據源和鏈接到咱們的同步管理器上 把數據源做爲key,數據庫鏈接做爲value 設置到線程變量中 if (txObject.isNewConnectionHolder()) { TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder()); } } catch (Throwable ex) { if (txObject.isNewConnectionHolder()) { //釋放數據庫鏈接 DataSourceUtils.releaseConnection(con, obtainDataSource()); txObject.setConnectionHolder(null, false); } throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex); } }
⑥ 進入到prepareSynchronization(status, definition)方法:
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) { if (status.isNewSynchronization()) { //綁定事務激活 TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction()); //當前事務的隔離級別 TransactionSynchronizationManager.setCurrentTransactionIsolationLevel( definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ? definition.getIsolationLevel() : null); //是否爲只讀事務 TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly()); //事務的名稱 TransactionSynchronizationManager.setCurrentTransactionName(definition.getName()); TransactionSynchronizationManager.initSynchronization(); } }
protected TransactionInfo prepareTransactionInfo(PlatformTransactionManager tm, TransactionAttribute txAttr, String joinpointIdentification, TransactionStatus status) { TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification); if (txAttr != null) { // We need a transaction for this method... if (logger.isTraceEnabled()) { logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]"); } // The transaction manager will flag an error if an incompatible tx already exists. txInfo.newTransactionStatus(status); } else { // The TransactionInfo.hasTransaction() method will return false. We created it only // to preserve the integrity of the ThreadLocal stack maintained in this class. if (logger.isTraceEnabled()) logger.trace("Don't need to create transaction for [" + joinpointIdentification + "]: This method isn't transactional."); } // We always bind the TransactionInfo to the thread, even if we didn't create // a new transaction here. This guarantees that the TransactionInfo stack // will be managed correctly even if no transaction was created by this aspect. txInfo.bindToThread(); return txInfo; }
執行流程參考前面的addUser流程,區別是到AbstractPlatformTransactionManager#getTransaction裏面的isExistingTransaction (transaction),這個時候是返回true的,因此執行handleExistingTransaction(definition, transaction, debugEnabled)方法:
private TransactionStatus handleExistingTransaction( TransactionDefinition definition, Object transaction, boolean debugEnabled) throws TransactionException { /** * 判斷當前的事務行爲是否是PROPAGATION_NEVER的 * 表示爲不支持事務,可是當前又存在一個事務,因此拋出異常 */ if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) { throw new IllegalTransactionStateException( "Existing transaction found for transaction marked with propagation 'never'"); } /** * 判斷當前的事務屬性不支持事務,PROPAGATION_NOT_SUPPORTED,因此須要先掛起已經存在的事務 */ if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) { if (debugEnabled) { logger.debug("Suspending current transaction"); } //掛起存在的事務 Object suspendedResources = suspend(transaction); boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); //建立一個新的非事務狀態(保存了上一個存在事務狀態的屬性) return prepareTransactionStatus( definition, null, false, newSynchronization, debugEnabled, suspendedResources); } /** * 當前的事務屬性狀態是PROPAGATION_REQUIRES_NEW表示須要新開啓一個事務狀態 */ if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) { if (debugEnabled) { logger.debug("Suspending current transaction, creating new transaction with name [" + definition.getName() + "]"); } //掛起已經存在的事務 SuspendedResourcesHolder suspendedResources = suspend(transaction); try { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); //建立一個新的事務狀態(包含了掛起的事務的屬性) DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); //開啓新的事務 doBegin(transaction, definition); //把新的事務狀態設置到當前的線程變量中去 prepareSynchronization(status, definition); return status; } catch (RuntimeException | Error beginEx) { resumeAfterBeginException(transaction, suspendedResources, beginEx); throw beginEx; } } if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { if (!isNestedTransactionAllowed()) { throw new NestedTransactionNotSupportedException( "Transaction manager does not allow nested transactions by default - " + "specify 'nestedTransactionAllowed' property with value 'true'"); } if (debugEnabled) { logger.debug("Creating nested transaction with name [" + definition.getName() + "]"); } //嵌套事務的處理 if (useSavepointForNestedTransaction()) { //開啓一個新的事務 DefaultTransactionStatus status = prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null); //爲事務設置一個回退點 status.createAndHoldSavepoint(); return status; } else {// Nested transaction through nested begin and commit/rollback calls. // Usually only for JTA: Spring synchronization might get activated here // in case of a pre-existing JTA transaction. boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, null); doBegin(transaction, definition); prepareSynchronization(status, definition); return status; } } // Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED. if (debugEnabled) { logger.debug("Participating in existing transaction"); } if (isValidateExistingTransaction()) { if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel(); if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) { Constants isoConstants = DefaultTransactionDefinition.constants; throw new IllegalTransactionStateException("Participating transaction with definition [" + definition + "] specifies isolation level which is incompatible with existing transaction: " + (currentIsolationLevel != null ? isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) : "(unknown)")); } } if (!definition.isReadOnly()) { if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) { throw new IllegalTransactionStateException("Participating transaction with definition [" + definition + "] is not marked as read-only but existing transaction is"); } } } boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null); }
因爲addLog上面的事務註解的傳播機制是TransactionDefinition.PROPAGATION_NESTED,因此執行下面分支
能夠看出內嵌事務設置保存點,也就是說內嵌事務的異常回滾是回滾到該保存點的,只要外層封裝事務捕獲了內嵌事務的異常,內嵌事務的回滾是不會影響外層封裝事務的。從demo的例子就能體現這點。接下來又回到addUser方法:
示例demo中的目標方法以下:
@Transactional(propagation = Propagation.NESTED,rollbackFor = Exception.class) public void addLog(String operation) { logDao.addLog(operation); System.out.println(1/0); }
1/0會報java.lang.ArithmeticException: / by zero異常,因此被catch捕獲到,從而進行回滾,此時因爲前面內嵌事務設置了保存點,因此內嵌事務值回滾到保存點,對外面沒有影響。內嵌事務執行完了以後,繼續外層addUser的方法執行
addUser方法捕獲了logService.addLog("新增用戶")異常以下:
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class) public void addUser(User user) { userDao.addUser(user.getName(),user.getSex(),user.getAddress()); //演示Propagation.NESTED 內嵌事務不影響外部事務 try { logService.addLog("新增用戶"); } catch (Exception e) { e.printStackTrace(); } }
因此外層事務的仍是能正常提交事務
至此整個addUser方法執行完畢!!!!
總結:首先經過事務概述,對事務的ACID特性,事務的隔離級別,Spring事務的傳播機制有了必定的認識,而後分析了@EnableTransactionManagement註解開啓Spring事務的支持功能,該註解爲咱們Spring容器中註冊了InfrastructureAdvisorAutoProxyCreator組件,Spring事務代理建立都在這個組件中完成,而後經過一個較爲複雜的嵌套事務的調用過程分析,進一步加深對Spring事務的傳播機制理解。Spring系列完整代碼在碼雲:spring系列