Spring事务三大接口介绍
- PlatformTransactionManager: (平台)事务管理器
- TransactionDefinition:事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则
- TransactionStatus: 事务运行状态
PlatformTransactionManager接口介绍
Spring并不直接管理事务,而是提供了多种事务管理器
,他们将事务管理的职责委托给Hibernate或者JTA等持 久化机制所提供的相关平台框架的事务来实现。 Spring事务管理器的接口是:org.springframework.transaction.PlatformTransactionManager
,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现 就是各个平台自己的事情了。
package org.springframework.transaction;
import org.springframework.lang.Nullable;
public interface PlatformTransactionManager extends TransactionManager {
/**
* 获取事物状态
*/
TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException;
/**
* 事物提交
*/
void commit(TransactionStatus status) throws TransactionException;
/**
* 事物回滚
*/
void rollback(TransactionStatus status) throws TransactionException;
}
TransactionDefinition 事物属性的定义
TransactionDefinition接口中定义了5个方法
以及一些表示事务属性的常量
比如隔离级别、传播行为等的常量。 我下面只是列出了TransactionDefinition接口中的方法而没有给出接口中定义的常量,该接口中的常量 信息会在后面依次介绍到
package org.springframework.transaction;
import org.springframework.lang.Nullable;
public interface TransactionDefinition {
/**
* 支持当前事物,若当前没有事物就创建一个事物
*/
int PROPAGATION_REQUIRED = 0;
/**
* 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行
*/
int PROPAGATION_SUPPORTS = 1;
/**
* 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常
*/
int PROPAGATION_MANDATORY = 2;
/**
* 创建一个新的事务,如果当前存在事务,则把当前事务挂起
*/
int PROPAGATION_REQUIRES_NEW = 3;
/**
* 以非事务方式运行,如果当前存在事务,则把当前事务挂起
*/
int PROPAGATION_NOT_SUPPORTED = 4;
/**
* 以非事务方式运行,如果当前存在事务,则抛出异常。
*/
int PROPAGATION_NEVER = 5;
/**
* 表示如果当前正有一个事务在运行中,则该方法应该运行在 一个嵌套的事务中,
* 被嵌套的事务可以独立于封装事务进行提交或者回滚(保存点),
* 如果封装事务不存在,行为就像 PROPAGATION_REQUIRES NEW
*/
int PROPAGATION_NESTED = 6;
/**
* 使用后端数据库默认的隔离级别,
* Mysql 默认采用的 REPEATABLE_READ隔离级别
* Oracle 默认采用的 READ_COMMITTED隔离级别
*/
int ISOLATION_DEFAULT = -1;
/**
* 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
*/
int ISOLATION_READ_UNCOMMITTED = 1;
// same as java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;
/**
* 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
*/
int ISOLATION_READ_COMMITTED = 2;
// same as java.sql.Connection.TRANSACTION_READ_COMMITTED;
/**
* 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,
* 可以阻止脏读和不可重复读,但幻读仍有可能发生
*/
int ISOLATION_REPEATABLE_READ = 4;
// same as java.sql.Connection.TRANSACTION_REPEATABLE_READ;
/**
* 最高的隔离级别,完全服从ACID的隔离级别。
* 所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,
* 也就是说,该级别可以防止脏读、不可重复读以及幻读。
* 但是这将严重影响程序的性能通常情况下也不会用到该级别
*/
int ISOLATION_SERIALIZABLE = 8;
// same as java.sql.Connection.TRANSACTION_SERIALIZABLE;
/**
* 使用默认的超时时间
*/
int TIMEOUT_DEFAULT = -1;
/**
* 获取事物的传播行为
*/
default int getPropagationBehavior() {
return PROPAGATION_REQUIRED;
}
/**
* 获取事物的隔离级别
*/
default int getIsolationLevel() {
return ISOLATION_DEFAULT;
}
/**
* 返回事物的超时时间
*/
default int getTimeout() {
return TIMEOUT_DEFAULT;
}
/**
* 返回当前是否为只读事物
*/
default boolean isReadOnly() {
return false;
}
/**
* 获取事物的名称
*/
@Nullable
default String getName() {
return null;
}
}
TransactionStatus接口介绍
TransactionStatus接口用来记录事务的状态 该接口定义了一组方法,用来获取或判断事务的相应状态信 息.
PlatformTransactionManager.getTransaction(…) 方法返回一个 TransactionStatus 对象。返回的 TransactionStatus 对象可能代表一个新的或已经存在的事务(如果在当前调用堆栈有一个符合条件的 事物
package org.springframework.transaction;
import java.io.Flushable;
public interface TransactionStatus extends SavepointManager, Flushable {
/**
* 是否为新事物
*/
boolean isNewTransaction();
/**
* 是否有保存点
*/
boolean hasSavepoint();
/**
* 设置为只回滚
*/
void setRollbackOnly();
/**
* 是否为只回滚
*/
boolean isRollbackOnly();
/**
* 属性
*/
@Override
void flush();
/**
* 判断当前事物是否已经完成
*/
boolean isCompleted();
}
我们来分析@EnableTransactionManagement注解来给我们容器加入了什么组件
从源码开始分析注册的组件
EnableTransactionManagement源码分析
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
/**
* 指定使用什么代理模式(true为cglib代理,false 为jdk代理)
*/
boolean proxyTargetClass() default false;
/**
* 通知模式 是使用代理模式还是aspectj 我们一般使用Proxy
*/
AdviceMode mode() default AdviceMode.PROXY;
/**
* Indicate the ordering of the execution of the transaction advisor
* when multiple advices are applied at a specific joinpoint.
* <p>The default is {@link Ordered#LOWEST_PRECEDENCE}.
*/
int order() default Ordered.LOWEST_PRECEDENCE;
}
我们从上面处的源码可以分析处他通过@Import导入了 TransactionManagementConfigurationSelector组件
TransactionManagementConfigurationSelector源码分析
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
/**
* 往容器中添加组件
* 1) AutoProxyRegistrar
* 2) ProxyTransactionManagementConfiguration
*/
@Override
protected String[] selectImports(AdviceMode adviceMode) {
//因为我们配置的默认模式是PROXY
switch (adviceMode) {
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
private String determineTransactionAspectClass() {
return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
}
}
首先我们来分析AutoProxyRegistrar给我们容器中干了什么?
从源码分析出,AutoProxyRegistrar
为我们容器注册了一个InfrastructureAdvisorAutoProxyCreator
组件
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
private final Log logger = LogFactory.getLog(getClass());
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
//从我们传入进去的配置类上获取所有的注解的
Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
//循环我们上一步获取的注解
for (String annoType : annoTypes) {
//获取注解的元信息
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
if (candidate == null) {
continue;
}
//获取注解的mode属性
Object mode = candidate.get("mode");
//获取注解的proxyTargetClass
Object proxyTargetClass = candidate.get("proxyTargetClass");
//根据mode和proxyTargetClass的判断来注册不同的组件
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
if (mode == AdviceMode.PROXY) {
//重点进入到这一步
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
if (!candidateFound && logger.isInfoEnabled()) {
String name = getClass().getSimpleName();
logger.info(String.format("%s was imported but no annotations were found " +
"having both 'mode' and 'proxyTargetClass' attributes of type " +
"AdviceMode and boolean respectively. This means that auto proxy " +
"creator registration and configuration may not have occurred as " +
"intended, and components may not be proxied as expected. Check to " +
"ensure that %s has been @Import'ed on the same class where these " +
"annotations are declared; otherwise remove the import of %s " +
"altogether.", name, name, name));
}
}
}
在这里我们可以看到,registerBeanDefinitions
方法中解析了 事务注解,并注册了自动代理创建器
。这里自动代理创建器我们在Aop 源码中提到过,是Aop 创建的核心。
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)
这一步最主要的作用将自动代理创建器 InfrastructureAdvisorAutoProxyCreator 注册到了 Spring容器中。
public abstract class AopConfigUtils {
/**
* ...略
*/
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAutoProxyCreatorIfNecessary(registry, null);
}
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//判断容器中有没有org.springframework.aop.config.internalAutoProxyCreator
//名字的bean定义
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
//自己注册一个org.springframework.aop.config.internalAutoProxyCreator的组件
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
/**
* ...略
*/
}
到这里我们基本可以断定和 Aop 的逻辑基本相同了,只不过事务默认自动注入的自动代理创建器是 InfrastructureAdvisorAutoProxyCreator 类型。
注意:
- 在上篇Aop 中我们知道 Aop创建的自动代理创建器类型是
AnnotationAwareAspectJAutoProxyCreator
,而事务创建的类型是InfrastructureAdvisorAutoProxyCreator
。 - 这里之所以 beanName (
AUTO_PROXY_CREATOR_BEAN_NAME
) 和 bean的类型并不相同,是因为这个beanName 特指内部的自动代理创建器
,但是自动创建代理器会对应多种不同的实现方式。比如在默认的事务中,注入的bean类型却为InfrastructureAdvisorAutoProxyCreator
,而AOP的实现却是AnnotationAwareAspectJAutoProxyCreator
。 - 关于自动代理创建器优先级的问题,我们可以看到
APC_PRIORITY_LIST
集合的顺序,下标越大,优先级越高。因此可以得知优先级的顺序应该是
InfrastructureAdvisorAutoProxyCreator
<AspectJAwareAdvisorAutoProxyCreator
<AnnotationAwareAspectJAutoProxyCreator
InfrastructureAdvisorAutoProxyCreator
我们看看InfrastructureAdvisorAutoProxyCreator的继承关系
这个类的继承关系是比较复杂的,我们只挑选我们最关注的来分析吧。
从图上可以看到InfrastructureAdvisorAutoProxyCreator类间接实现了BeanPostProcessor接口,这个接口主要的所用是对每一个bean对象初始化前后做增强。在每一个bean初始化前调用postProcessBeforeInitialization,初始化后调用postProcessAfterInitialization。
然后我们在来分析一下 TransactionManagementConfigurationSelector
为我们还导入了一个类 ProxyTransactionManagementConfiguration
@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
/**
* 为我我们容器中导入了
* beanName为org.springframework.transaction.config.internalTransactionAdvisor
* 类型为BeanFactoryTransactionAttributeSourceAdvisor
* 的增强器
*/
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource());
advisor.setAdvice(transactionInterceptor());
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
/**
* 定义了一个事物属性源对象
*/
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
/**
* 事物拦截器对象
*/
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor() {
TransactionInterceptor interceptor = new TransactionInterceptor();
//把事物属性源对象设置到我们的事物拦截器对象中
interceptor.setTransactionAttributeSource(transactionAttributeSource());
//把我们容器中的 事物对象配置到事物拦截器中
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
ProxyTransactionManagementConfiguration
代码如下,并没有逻辑,就是将几个Bean注入的到容器中。不过这几个bean可都是关键bean,所以我们需要对其中的bean进行分析。
BeanFactoryTransactionAttributeSourceAdvisor
: 事务的增强器,该方法是否开始事务,是否需要代理该类都在该类中判断TransactionAttributeSource
: 保存了事务相关的一些信息资源。TransactionInterceptor
: 事务拦截器,事务生成代理类时使用的代理拦截器,编写了事务的规则
@SuppressWarnings("serial")
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
@Nullable
private TransactionAttributeSource transactionAttributeSource;
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
@Nullable
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
/**
* Set the transaction attribute source which is used to find transaction
* attributes. This should usually be identical to the source reference
* set on the transaction interceptor itself.
* @see TransactionInterceptor#setTransactionAttributeSource
*/
public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
this.transactionAttributeSource = transactionAttributeSource;
}
/**
* Set the {@link ClassFilter} to use for this pointcut.
* Default is {@link ClassFilter#TRUE}.
*/
public void setClassFilter(ClassFilter classFilter) {
this.pointcut.setClassFilter(classFilter);
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
}
这个根据上面的分析,我们可以知道这个是事务判断的核心,BeanFactoryTransactionAttributeSourceAdvisor
是Advisor
子类,那么我们可以知道其中有两个关键属性: Pointcut(判断是否可以作用于当前方法)
和 Advice(作用于当前方法的具体逻辑)
。
通过 Aop文章的分析我们可以知道,Advisor 判断一个方法是否匹配,是通过其 Pointcut.matchs
属性来判断的。然后我们通过上面的代码,发现其 Pointcut 的实现类是 TransactionAttributeSourcePointcut
,也就是说,一个方法是否需要使用事务,是通过 TransactionAttributeSourcePointcut#matches
方法判断的。
TransactionAttributeSourcePointcut
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
@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();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof TransactionAttributeSourcePointcut)) {
return false;
}
TransactionAttributeSourcePointcut otherPc = (TransactionAttributeSourcePointcut) other;
return ObjectUtils.nullSafeEquals(getTransactionAttributeSource(), otherPc.getTransactionAttributeSource());
}
@Override
public int hashCode() {
return TransactionAttributeSourcePointcut.class.hashCode();
}
@Override
public String toString() {
return getClass().getName() + ": " + getTransactionAttributeSource();
}
/**
* Obtain the underlying TransactionAttributeSource (may be {@code null}).
* To be implemented by subclasses.
*/
@Nullable
protected abstract TransactionAttributeSource getTransactionAttributeSource();
}
AnnotationTransactionAttributeSource
@SuppressWarnings("serial")
public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource
implements Serializable {
// JTA 1.2事务注解是否被使用
private static final boolean jta12Present;
// EJB 3 事务注解是否被使用
private static final boolean ejb3Present;
static {
ClassLoader classLoader = AnnotationTransactionAttributeSource.class.getClassLoader();
// 根据注解类的存在性判断 JTA 1.2 事务注解是否被使用
jta12Present = ClassUtils.isPresent("javax.transaction.Transactional", classLoader);
// 根据注解类的存在性判断 EJB 3 事务注解是否被使用
ejb3Present = ClassUtils.isPresent("javax.ejb.TransactionAttribute", classLoader);
}
// 指出仅仅处理public方法(基于代理的AOP情况下的典型做法),
// 还是也处理protected/private方法(使用AspectJ类织入方式下的典型做法)
private final boolean publicMethodsOnly;
// 保存用于分析事务注解的事务注解分析器
private final Set<TransactionAnnotationParser> annotationParsers;
/**
* 构造函数, publicMethodsOnly 缺省使用 true
*/
public AnnotationTransactionAttributeSource() {
this(true);
}
/**
* 构造函数
*/
public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
this.publicMethodsOnly = publicMethodsOnly;
// 下面这段逻辑主要是准备用于分析事务注解的各个分析器,放到属性 annotationParsers 中
// Spring事务注解分析器总是
// 会被使用 : SpringTransactionAnnotationParser
if (jta12Present || ejb3Present) {
// 根据 JTA , EJB 事务注解类的存在性决定要不要添加相应的事务注解处理器
// JTA 事务注解分析器 : JtaTransactionAnnotationParser
// EJB 事务注解分析器 : Ejb3TransactionAnnotationParser
this.annotationParsers = new LinkedHashSet<>(4);
this.annotationParsers.add(new SpringTransactionAnnotationParser());
if (jta12Present) {
this.annotationParsers.add(new JtaTransactionAnnotationParser());
}
if (ejb3Present) {
this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
}
}
else {
this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
}
}
/**
* 创建一个定制的 AnnotationTransactionAttributeSource ,使用给定的事务注解分析器(一个),
* publicMethodsOnly 缺省使用 true,仅针对public方法工作
*/
public AnnotationTransactionAttributeSource(TransactionAnnotationParser annotationParser) {
this.publicMethodsOnly = true;
Assert.notNull(annotationParser, "TransactionAnnotationParser must not be null");
this.annotationParsers = Collections.singleton(annotationParser);
}
/**
* 创建一个定制的 AnnotationTransactionAttributeSource ,使用给定的事务注解分析器(多个),
* publicMethodsOnly 缺省使用 true,仅针对public方法工作
*/
public AnnotationTransactionAttributeSource(TransactionAnnotationParser... annotationParsers) {
this.publicMethodsOnly = true;
Assert.notEmpty(annotationParsers, "At least one TransactionAnnotationParser needs to be specified");
this.annotationParsers = new LinkedHashSet<>(Arrays.asList(annotationParsers));
}
/**
* 创建一个定制的 AnnotationTransactionAttributeSource ,使用给定的事务注解分析器(多个),
* publicMethodsOnly 缺省使用 true,仅针对public方法工作
*/
public AnnotationTransactionAttributeSource(Set<TransactionAnnotationParser> annotationParsers) {
this.publicMethodsOnly = true;
Assert.notEmpty(annotationParsers, "At least one TransactionAnnotationParser needs to be specified");
this.annotationParsers = annotationParsers;
}
// 获取某个类上的事务注解属性
@Override
@Nullable
protected TransactionAttribute findTransactionAttribute(Class<?> clazz) {
return determineTransactionAttribute(clazz);
}
// 获取某个方法上的事务注解属性
@Override
@Nullable
protected TransactionAttribute findTransactionAttribute(Method method) {
return determineTransactionAttribute(method);
}
/**
* 分析获取某个被注解的元素,具体的来讲,指的是一个类或者一个方法上的事务注解属性。
* 该实现会遍历自己属性annotationParsers中所包含的事务注解属性分析器试图获取事务注解属性,
* 一旦获取到事务注解属性则返回,如果获取不到则返回null,表明目标类/方法上没有事务注解。
*/
@Nullable
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element);
if (attr != null) {
return attr;
}
}
return null;
}
/**
* 缺省情况下,仅仅public方法上的事务注解才被识别和应用
*/
@Override
protected boolean allowPublicMethodsOnly() {
return this.publicMethodsOnly;
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof AnnotationTransactionAttributeSource)) {
return false;
}
AnnotationTransactionAttributeSource otherTas = (AnnotationTransactionAttributeSource) other;
return (this.annotationParsers.equals(otherTas.annotationParsers) &&
this.publicMethodsOnly == otherTas.publicMethodsOnly);
}
@Override
public int hashCode() {
return this.annotationParsers.hashCode();
}
}
- 从类
AnnotationTransactionAttributeSource
的源代码可以看到,它仅仅通过findTransactionAttribute
方法实现类如何找到指定类/方法的事务注解属性,但是自身并没有提供public
方法供调用者使用。 - 实际上,类
AnnotationTransactionAttributeSource
提供给调用者的服务方法是getTransactionAttribute
,而该方法定义在其父类AbstractFallbackTransactionAttributeSource
中。
public abstract class AbstractFallbackTransactionAttributeSource implements TransactionAttributeSource {
/**
* 针对没有事务注解属性的方法进行事务注解属性缓存时使用的特殊值,用于标记该方法没有事务注解属性,
* 从而不用在首次缓存在信息后,不用再次重复执行真正的分析
*/
@SuppressWarnings("serial")
private static final TransactionAttribute NULL_TRANSACTION_ATTRIBUTE = new DefaultTransactionAttribute() {
@Override
public String toString() {
return "null";
}
};
/**
* Logger available to subclasses.
* <p>As this base class is not marked Serializable, the logger will be recreated
* after serialization - provided that the concrete subclass is Serializable.
*/
protected final Log logger = LogFactory.getLog(getClass());
/**
* 方法上的事务注解属性缓存,key使用目标类上的方法,使用类型MethodClassKey来表示
*/
private final Map<Object, TransactionAttribute> attributeCache = new ConcurrentHashMap<>(1024);
/**
* 获取指定方法上的注解事务属性
* 如果方法上没有注解事务属性,则使用目标方法所属类上的注解事务属性
*/
@Override
@Nullable
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
// 如果目标方法是内置类Object上的方法,总是返回null,这些方法上不应用事务
return null;
}
// 先查看针对该方法是否已经获取过其注解事务属性并且已经缓存
Object cacheKey = getCacheKey(method, targetClass);
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
// 目标方法上的事务注解属性信息已经缓存的情况
// or an actual transaction attribute.
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
// 目标方法上上并没有事务注解属性,但是已经被尝试分析过并且已经被缓存,
// 使用的值是 NULL_TRANSACTION_ATTRIBUTE,所以这里再次尝试获取其注解事务属性时,
// 直接返回 null
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.isTraceEnabled()) {
logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
}
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
}
/**
* Determine a cache key for the given method and target class.
* <p>Must not produce same key for overloaded methods.
* Must produce same key for different instances of the same method.
* @param method the method (never {@code null})
* @param targetClass the target class (may be {@code null})
* @return the cache key (never {@code null})
*/
protected Object getCacheKey(Method method, @Nullable Class<?> targetClass) {
return new MethodClassKey(method, targetClass);
}
/**
* 查找目标方法上的事务注解属性,但只是查找和返回,并不做缓存,效果上讲,可以认为
* #getTransactionAttribute 是增加了缓存机制的方法#computeTransactionAttribute
*/
@Nullable
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// 如果事务注解属性分析仅仅针对public方法,而当前方法不是public,则直接返回null
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
// 参数 method 可能是基于接口的方法,该接口和参数targetClass所对应的类不同(也就是说:
// targetClass是相应接口的某个实现类),而我们这里需要的属性是要来自targetClass的,
// 所以这里先获取targetClass上的那个和method对应的方法,这里 method, specificMethod
// 都可以认为是潜在的目标方法
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
// 首先尝试检查事务注解属性直接标记在目标方法 specificMethod 上
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
// 事务注解属性直接标记在目标方法上
return txAttr;
}
// 然后尝试检查事务注解属性是否标记在目标方法 specificMethod 所属类上
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
// 事务注解属性是否标记在目标方法所属类上
return txAttr;
}
// 逻辑走到这里说明目标方法specificMethod,也就是实现类上的目标方法上没有标记事务注解属性
if (specificMethod != method) {
// 如果 specificMethod 和 method 不同,则说明 specificMethod 是具体实现类
// 的方法,method 是实现类所实现接口的方法,现在尝试从 method 上获取事务注解属性
txAttr = findTransactionAttribute(method);
if (txAttr != null) {
return txAttr;
}
// 现在尝试在 method 所属类上查看是否有事务注解属性
txAttr = findTransactionAttribute(method.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}
// specificMethod 方法/所属类上没有事务注解属性,
// method 方法/所属类上也没有事务注解属性,
// 所以返回 null
return null;
}
/**
* 从指定类上获取事务注解属性,由子类负责提供实现
*/
@Nullable
protected abstract TransactionAttribute findTransactionAttribute(Class<?> clazz);
/**
* 从指定方法上获取事务注解属性,由子类负责提供实现
*/
@Nullable
protected abstract TransactionAttribute findTransactionAttribute(Method method);
/**
* Should only public methods be allowed to have transactional semantics?
* <p>The default implementation returns {@code false}.
*/
protected boolean allowPublicMethodsOnly() {
return false;
}
}
AbstractFallbackTransactionAttributeSource
是接口TransactionAttributeSource
的抽象实现,也是上面提到的工具类AnnotationTransactionAttributeSource
的父类。- 方法
AbstractFallbackTransactionAttributeSource#getTransactionAttribute
是给调用者使用的获取指定方法的事务注解属性的入口
我们的分析到这里,就已经可以知道了Spring 中对事务注解的解析过程,逻辑基本和 Spring Aop 类似。
@EnableTransactionManagement
通过引入TransactionManagementConfigurationSelector
注册了AutoProxyRegistrar
和ProxyTransactionManagementConfiguration
两个类。AutoProxyRegistrar
中注册了InfrastructureAdvisorAutoProxyCreator
自动代理创建器InfrastructureAdvisorAutoProxyCreator
中拦截bean的创建过程,通过BeanFactoryTransactionAttributeSourceAdvisor
来判断bean中是否有事务注解,有则进行代理。
TransactionInterceptor
@SuppressWarnings("serial")
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
/**
* ... 略
*/
@Override
@Nullable
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);
}
/**
* ... 略
*/
}
public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// 获取事务数据源,这里获取的数据源就是在 TransactionInterceptor 注入的时候的设置的属性transactionAttributeSource = AnnotationTransactionAttributeSource。
// 在 ProxyTransactionManagementConfiguration 中完成
TransactionAttributeSource tas = getTransactionAttributeSource();
// 1. 获取对应的事务属性
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
// 2. 获取一个合适的 TransactionManager
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
// 构造方法的唯一标识( 全路径了类名.方法)
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
// 4. 对不同事务情景的处理
// 声明式事务的处理
// 如果txAttr为空或者tm 属于非CallbackPreferringPlatformTransactionManager,执行目标增强
// 在TransactionManager上,CallbackPreferringPlatformTransactionManager实现PlatformTransactionManager接口,暴露出一个方法用于执行事务处理中的回调
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// 5.如果有必要,创建事务信息。主要由于事务的传播属性,所以这里并不一定会创建事务
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
// 6. 执行被增强的方法
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// 7. 异常回滚
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
// 8. 提交之前清除事务信息
cleanupTransactionInfo(txInfo);
}
// 9.提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
// 编程式事务(CallbackPreferringPlatformTransactionManager)的处理。这里的逻辑基本都被封装了
else {
final ThrowableHolder throwableHolder = new ThrowableHolder();
// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
try {
// 直接调用execute 方法。由于事务的提交回滚等操作都已经封装好了,所以这里并没有对事务进行详细的操作。
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;
}
}
}
}
从上面的代码中,我们可以知道Spring支持声明式事务和编程式事务两种处理。两者的实现本质基本相同。在invoke方法中我们也可以看到这两种方式的实现,通常我们使用的都是通过 @Transactional 注解修饰的声明式事务,所以我们下面主要分析 声明式事务 的处理过程。
-
获取事务属性
TransactionAttribute
,TransactionAttribute 中包含 传播属性,timeout 等事务属性信息。如果是使用@Transactional
注解,这个解析过程是在AnnotationTransactionAttributeSource#findTransactionAttribute(java.lang.reflect.Method)
中完成 -
加载配置中的
TrancationManager
, 事务管理器,是事务实现的基础,我们这里获取到的是DataSourceTransactionManager
。 -
对反应式事务的处理。
-
不同事务处理方式使用不同的逻辑。在上面的代码中主要是两种情况,一是
声明式事务
,这种情况是通过@Transactional
注解修饰方法来表示开启事务。另一种情况是编程式事务
,即可以通过xml方式或者配置类方式来进行完成事务功能,其实TransactionTemplate
的实现就是编程式事务,但通过TransactionTemplate
并不会走到这个逻辑,这里的编程式事务应该单独是通过xml或者配置类方式来配置的。
对于声明式事务的处理和编程式事务的处理,区别主要在两点。一是事务属性上,因为编程式事务是不需要事务属性的,二是TransactionManager
的不同,CallbackPreferringPlatformTransactionManager
实现了PlatformTransactionManager
接口,暴露了一个方法用于执行事务处理中的回调。所以这两种方式都可以作为事务处理方式的判断。 -
在目标方法执行前获取事务并收集事务信息。
事务信息与事务属性并不相同,也就是TransactionInfo
和TransactionAttribute
并不相同,TransactionInfo
中包含TransactionAttribute
信息,并且处理TransactionAttribute
之外还有其他事物信息,比如PlatformTransactionManager
以及TransactionStatus
相关信息。 -
执行目标方法
-
如果出现异常,则进行回滚。这里需要注意,默认的情况下只有 RuntimeException 异常才会执行回滚。可以通过
@Transactional(rollbackFor = Exception.class)
的方式来指定触发回滚的异常 -
提交事务前的事务信息清除
-
提交事务
-
若是 编程式事务,则直接执行execute方法即可,这里就不再讲解。