Spring 事务核心
Spring 事务处理方式分为两种:编程式事务,申明式事务。我们常用的注解的方式也是申明式事务,如果我们通过手动去开启事务,正常完成进行 commit
异常进行 fallback
这种就是编程式事务。我们主要描述申明式事务的实现
启用事务管理
- @EnableTransactionManagement 定义如下,在这了加载一个 TransactionManagementConfigurationSelector
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(TransactionManagementConfigurationSelector.class) public @interface EnableTransactionManagement { // ... }
- TransactionManagementConfigurationSelector 是一个 ImportSelector 加载了两个类 AutoProxyRegistrar 和 ProxyTransactionManagementConfiguration 。
@Override protected String[] selectImports(AdviceMode adviceMode) { switch (adviceMode) { case PROXY: //向 Spring 中添加了 AutoProxyRegistrar 和 ProxyTransactionManagementConfiguration 对应的 bean return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()}; case ASPECTJ: return new String[] {determineTransactionAspectClass()}; default: return null; } }
3.AutoProxyRegistrar
其实是一个自动代理创建器
- AutoProxyRegistrar#registerBeanDefinitions() // 注册自动代理创建器 -- AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry); // 注册一个 InfrastructureAdvisorAutoProxyCreator 其实它也是实现了 BeanPostProcessor -- registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
ProxyTransactionManagementConfiguration
其实是一个代理逻辑Advisor
包含了Poincut
和Advice
@Configuration @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() { BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor(); //表示切点 advisor.setTransactionAttributeSource(transactionAttributeSource()); //表示 advice 代理逻辑 advisor.setAdvice(transactionInterceptor()); if (this.enableTx != null) { advisor.setOrder(this.enableTx.<Integer>getNumber("order")); } return advisor; } // TransactionAttributeSource 表示 @Transaction 所包含的信息 @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionAttributeSource transactionAttributeSource() { return new AnnotationTransactionAttributeSource(); } // TransactionInterceptor 这里其实是一个代理的逻辑的细节 @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionInterceptor transactionInterceptor() { TransactionInterceptor interceptor = new TransactionInterceptor(); //拦截器中持有的 @Transaction 注解信息 interceptor.setTransactionAttributeSource(transactionAttributeSource()); if (this.txManager != null) { interceptor.setTransactionManager(this.txManager); } return interceptor; } } // TransactionInterceptor 类 public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable { // ... @Override @Nullable public Object invoke(MethodInvocation invocation) throws Throwable { // Work out the target class: may be {@code null}. // The TransactionAttributeSource should be passed the target class // as well as the method, which may be from an interface. Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); // Adapt to TransactionAspectSupport's invokeWithinTransaction... // 执行代理逻辑 return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed); } } // BeanFactoryTransactionAttributeSourceAdvisor 中定义 public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor { // 构造了一个 Pointcut, TransactionAttributeSource 的实现对象为 AnnotationTransactionAttributeSource // 在 Pointcut 匹配类时, 会利用 AnnotationTransactionAttributeSource 去检查类上是否有 @Transaction 注解 // 在 Pointcut 匹配方法时, 会利用 AnnotationTransactionAttributeSource 去检查方法上是否有 @Transaction 注解 private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() { @Override @Nullable protected TransactionAttributeSource getTransactionAttributeSource() { return transactionAttributeSource; } }; @Override public Pointcut getPointcut() { return this.pointcut; } } // TransactionAttributeSourcePointcut#matches 进行匹配方法/类上面是否包含 @Transaction 注解 abstract class TransactionAttributeSourcePointcut@ extends StaticMethodMatcherPointcut implements Serializable { /** * 判断 某个方法或者类 是否存在 @Transaction 注解 * @param method the candidate method * @param targetClass the target class * @return */ @Override public boolean matches(Method method, Class<?> targetClass) { if (TransactionalProxy.class.isAssignableFrom(targetClass) || PlatformTransactionManager.class.isAssignableFrom(targetClass) || PersistenceExceptionTranslator.class.isAssignableFrom(targetClass)) { return false; } TransactionAttributeSource tas = getTransactionAttributeSource(); //某个类或者方法上是否存在 @Transaction 注解 //调用 AnnotationTransactionAttributeSource 的父类中的 getTransactionAttribute 方法 //按段是否有 @Transaction 注解, 获取到注解信息不等于 null 则匹配 return (tas == null || tas.getTransactionAttribute(method, targetClass) != null); } } //tas.getTransactionAttribute(method, targetClass) @Override @Nullable public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) { if (method.getDeclaringClass() == Object.class) { return null; } // First, see if we have a cached value. Object cacheKey = getCacheKey(method, targetClass); TransactionAttribute cached = this.attributeCache.get(cacheKey); if (cached != null) { // Value will either be canonical value indicating there is no transaction attribute, // or an actual transaction attribute. if (cached == NULL_TRANSACTION_ATTRIBUTE) { return null; } else { return cached; } } else { // We need to work it out. // 获取 @Transactional 注解信息 TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass); // Put it in the cache. 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.isTraceEnabled()) { logger.trace("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) { // Don't allow no-public methods as required. // allowPublicMethodsOnly 默认为 false, 所以在 public 方法上写上 @Transactional 注解没有作用 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); // First try is the method in the target class. TransactionAttribute txAttr = findTransactionAttribute(specificMethod); if (txAttr != null) { return txAttr; } // Second try is the transaction attribute on the target class. txAttr = findTransactionAttribute(specificMethod.getDeclaringClass()); if (txAttr != null && ClassUtils.isUserLevelMethod(method)) { return txAttr; } if (specificMethod != method) { // Fallback is to look at the original method. txAttr = findTransactionAttribute(method); if (txAttr != null) { return txAttr; } // Last fallback is the class of the original method. txAttr = findTransactionAttribute(method.getDeclaringClass()); if (txAttr != null && ClassUtils.isUserLevelMethod(method)) { return txAttr; } } return null; }
其实到这里可以得到一个结论:
@Transactional 注解对 public 方法才有效,其它的方法是无效的
TransactionInterceptor 对事务方法的执行
- TransactionInterceptor invoke 方法是事务执行的核心方法
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(); // 获取得到当前方法或者类上的 @Transactional 注解的信息 final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null); // 得到一个 @Transactional 注解的信息 final PlatformTransactionManager tm = determineTransactionManager(txAttr); // 根据当前执行的类中的某个方法以及 @Transactional 注解的信息生成一个唯一的标示, 这个标示会用来作为事务的名称 final String joinpointIdentification = methodIdentification(method, targetClass, txAttr); if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { // Standard transaction demarcation with getTransaction and commit/rollback calls. // 创建事务,并且得到当前事务的信息,后面需要事务信息来进行提交或者回滚 // 例如: cn.edu.xxx.tx.service.PersonService.test // 这里默认就是 类名全路径 + 方法名 TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal; 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 // 出现异常的清隽管辖,如果是异常需要 rollback , 否则就提交 completeTransactionAfterThrowing(txInfo, ex); // 出现了异常限制性 finally 中的逻辑再抛出异常 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; } } }