Spring 事務原理
阿新 • • 發佈:2018-12-01
getc throws 事務 inter bsp normal The pri don
1,從@EnableTransactionManagement 開始入手
2,看到它給容器註冊了 TransactionManagementConfigurationSelector 類
3,觀察其 selectImports 方法,發現它給容器註冊了兩個bean
4,分別是 AutoProxyRegistrar 和 ProxyTransactionManagementConfiguration ,這裏重點看下 ProxyTransactionManagementConfiguration
5,發現 proxyxxx 給容器註冊了 3個bean BeanFactoryTransactionAttributeSourceAdvisor(事務增強器) ,AnnotationTransactionAttributeSource(註解事務屬性),TransactionInterceptor(事務攔截器)
6,觀察 AnnotationTransactionAttributeSource ,發現它會解析@Transactional 的屬性
#SpringTransactionAnnotationParser 類 protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) { RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute(); Propagation propagation= attributes.getEnum("propagation"); rbta.setPropagationBehavior(propagation.value()); Isolation isolation = attributes.getEnum("isolation"); rbta.setIsolationLevel(isolation.value()); rbta.setTimeout(attributes.getNumber("timeout").intValue()); rbta.setReadOnly(attributes.getBoolean("readOnly")); rbta.setQualifier(attributes.getString("value")); ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<>(); Class<?>[] rbf = attributes.getClassArray("rollbackFor"); for (Class<?> rbRule : rbf) { RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule); rollBackRules.add(rule); } String[] rbfc = attributes.getStringArray("rollbackForClassName"); for (String rbRule : rbfc) { RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule); rollBackRules.add(rule); } Class<?>[] nrbf = attributes.getClassArray("noRollbackFor"); for (Class<?> rbRule : nrbf) { NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule); rollBackRules.add(rule); } String[] nrbfc = attributes.getStringArray("noRollbackForClassName"); for (String rbRule : nrbfc) { NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule); rollBackRules.add(rule); } rbta.getRollbackRules().addAll(rollBackRules); return rbta; }
7,再看 TransactionInterceptor ,發現它實現了 MethodInterceptor 也就是目標方法被調用的時候,實際執行的是 TransactionInterceptor 的 invoke 方法
8,觀察 invoke 方法 ,調用了 invokeWithinTransaction 方法
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, final InvocationCallback invocation) throws Throwable { // If the transaction attribute is null, the method is non-transactional. //拿到註解上的屬性 TransactionAttributeSource tas = getTransactionAttributeSource(); final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null); //拿到事務管理器 final PlatformTransactionManager tm = determineTransactionManager(txAttr); final String joinpointIdentification = methodIdentification(method, targetClass, txAttr); if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { // Standard transaction demarcation with getTransaction and commit/rollback calls. TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal = null; try { // This is an around advice: Invoke the next interceptor in the chain. // This will normally result in a target object being invoked. //執行目標方法,得到結果 retVal = invocation.proceedWithInvocation(); } catch (Throwable ex) { // target invocation exception //目標方法發生異常,利用事務管理器進行回滾 completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { //收尾工作 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; } } }
9,jdbc的事務開啟,提交和回滾,實際都是對 Connection 的操作
//開啟事務 if(cnn.getAutoCommit()){ cnn.setAutoCommit(false); } //提交事務 if(!cnn.getAutoCommit()){ cnn.commit(); } //回滾事務 if(!cnn.getAutoCommit()){ cnn.rollback(); }
Spring 事務原理