- Spring 声明式事务基于 AOP 实现,要么是 JDK、要么是 CGLIB。由 BeanPostProcessor 创建代理。在调用的时候过程中,动态的将原始功能和事务相关的额外功能整合在一起。
- Spring 事务的底层依附于 DataSource、Connection、ThreadLocal 实现,由 Connection 来控制事务的开启、回滚、提交。
事务管理核心类
PlatformTransactionManager
Spring 并不直接管理事务,而是提供了多种事务管理器 。Spring 事务管理器的接口是:PlatformTransactionManager
。
通过这个接口,Spring 为各个平台如:JDBC、MyBatis(DataSourceTransactionManager
)、Hibernate(HibernateTransactionManager
)、JPA(JpaTransactionManager
)等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。
PlatformTransactionManager 接口的具体实现如下:
此接口中定义了三个方法:
public interface PlatformTransactionManager {
// 获得事务
TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;
// 提交事务
void commit(TransactionStatus var1) throws TransactionException;
// 回滚事务
void rollback(TransactionStatus var1) throws TransactionException;
}
为什么要定义或者说抽象出来PlatformTransactionManager
这个接口呢?
主要是因为要将事务管理行为抽象出来,然后不同的平台去实现它,这样我们可以保证提供给外部的行为不变,方便我们扩展。
TransactionDefinition
事务管理器接口 PlatformTransactionManager 通过 getTransaction(TransactionDefinition definition)
方法来得到一个事务,这个方法里面的参数是 TransactionDefinition
类 ,这个类就定义了一些基本的事务属性。
事务属性可以理解成事务的一些基本配置,描述了事务策略如何应用到方法上。
事务属性包含了 5 个方面:
- 隔离级别
- 传播行为
- 回滚规则
- 是否只读
- 事务超时
TransactionDefinition
接口中定义了 5 个方法以及一些表示事务属性的常量比如隔离级别、传播行为等等。
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;
int PROPAGATION_NESTED = 6;
int ISOLATION_DEFAULT = -1;
int ISOLATION_READ_UNCOMMITTED = 1;
int ISOLATION_READ_COMMITTED = 2;
int ISOLATION_REPEATABLE_READ = 4;
int ISOLATION_SERIALIZABLE = 8;
int TIMEOUT_DEFAULT = -1;
// 返回事务的传播行为,默认值为 REQUIRED。
int getPropagationBehavior();
// 返回事务的隔离级别,默认值是 DEFAULT
int getIsolationLevel();
// 返回事务的超时时间,默认值为-1。如果超过该时间限制但事务还没有完成,则自动回滚事务。
int getTimeout();
// 返回是否为只读事务,默认值为 false
boolean isReadOnly();
@Nullable
String getName();
}
TransactionStatus
TransactionStatus 接口用来记录事务的状态,该接口定义了一组方法,用来获取或判断事务的相应状态信息。
PlatformTransactionManager.getTransaction(…)
方法返回一个 TransactionStatus
对象。
TransactionStatus 接口内容如下
public interface TransactionStatus{
// 是否是新的事务
boolean isNewTransaction();
// 是否有恢复点
boolean hasSavepoint();
// 设置为只回滚
void setRollbackOnly();
// 是否为只回滚
boolean isRollbackOnly();
// 是否已完成
boolean isCompleted;
}
初始化过程
通过查看 @EnableTransactionManagement 注解的源码,如下所示:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({TransactionManagementConfigurationSelector.class})
public @interface EnableTransactionManagement {
boolean proxyTargetClass() default false;
// 注意这里的模式 PROXY
AdviceMode mode() default AdviceMode. PROXY;
int order() default Integer.MAX_VALUE;
}
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
// 通过查看上面的注解,可以看到这个就是默认的模式
return new String[]{AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[]{this.determineTransactionAspectClass()};
default:
return null;
}
}
// 这个方法与 ASPECTJ 有关,可以不看
private String determineTransactionAspectClass() {
return ClassUtils.isPresent("javax.transaction.Transactional", this.getClass().getClassLoader()) ? "org.springframework.transaction.aspectj.AspectJJtaTransactionManagementConfiguration" : "org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration";
}
}
@EnableTransactionManagement 注解是通过使用 @Import({TransactionManagementConfigurationSelector.class}) 给容器中注册一个 AutoProxyRegistrar 和 ProxyTransactionManagementConfiguration 的组件。
- AutoProxyRegistrar:其实就是负责事务 AOP 的 BeanPostProcessor。
- ProxyTransactionManagementConfiguration:事务解析器,用来解析事务属性,包括配置 AOP 的通知/拦截器,切面等。
代理创建过程
AutoProxyRegistrar
AutoProxyRegistrar 给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件,利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用.
它会检测导入者类上的某个注解是否带有属性 mode
和 proxyTargetClass
,如果检测到这些属性,在 mode
为 PROXY
时,它会向容器注册一个自动代理创建器 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) {
// 遍历导入者类上使用的所有注解,找到第一个带有属性 mode/proxyTargetClass 属性的注解
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
if (candidate == null) {
continue;
}
Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
Boolean.class == proxyTargetClass.getClass()) {
// 找到第一个带有属性 mode/proxyTargetClass 属性的注解
candidateFound = true;
if (mode == AdviceMode.PROXY) {
// 在 mode 属性值为 PROXY 时,向容器注册一个自动代理创建器 InfrastructureAdvisorAutoProxyCreator
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
if (!candidateFound && this.logger.isInfoEnabled()) {
// 日志打印
}
}
}
public abstract class AopConfigUtils {
// ...
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
}
InfrastructureAdvisorAutoProxyCreator
它是 Spring 框架中的一个内部类,用于自动创建代理对象。在 Spring 的 AOP(面向切面编程)机制中,代理对象的创建是一个核心概念,它允许开发者通过切面(Aspect)来横切关注点(cross-cutting concerns),比如事务管理、日志记录等。
一般情况下,
InfrastructureAdvisorAutoProxyCreator
是由 Spring 框架自动配置和管理的,开发者无需直接与其交互。
主要功能
它是 Spring 的 AbstractAdvisorAutoProxyCreator 的子类,其主要功能包括:
- 自动创建代理:当 Spring 容器中的 Bean 被标记为需要代理时(例如,Bean 实现了某些接口,或者被
@Transactional
注解标记),它会自动创建这些 Bean 的代理对象。 - 管理 Advisor:Advisor 是 Spring AOP 的核心概念,它包含了切面逻辑和切入点。它可以自动管理这些 Advisor,并将它们应用到目标 Bean 上。
- 优化性能:通过缓存和优化代理对象的创建来提高性能。它只会为需要代理的 Bean 创建代理,从而避免了不必要的开销。
工作原理
- BeanFactoryPostProcessor:它实现了
BeanFactoryPostProcessor
接口,因此它在 Spring 容器初始化期间会被调用。它会检查所有的 Bean,并决定哪些 Bean 需要代理。 - 创建代理:一旦确定需要代理的 Bean,它会使用 Spring 的代理机制(如 JDK 动态代理或 CGLIB 代理)创建代理对象。
- 应用 Advisor:在创建代理的过程中,它会应用相关的 Advisor,将切面逻辑应用到目标 Bean 上。
创建代理过程
InfrastructureAdvisorAutoProxyCreator 创建代理的过程和 AOP 创建代理的过程是一模一样的,创建的代码都是写在父类 AbstractAutoProxyCreator 里面。
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
// ...
/**
* bean 是原始对象,beanName 是原始对象的 ID 值
*/
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 解决循环引用的问题,之前循环引用的处理也是可以提前通过 Lambda 创建代理对象的,如果之前已经创建过,则直接返回
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 真正创建代理的核心,判断是否需要代理并进行代理包装
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
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;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
// 这里是解决事务的情况
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 下面这一段是创建代理的核心逻辑
// 获取当前 Bean 的拦截器(其实就是我们的切面和额外功能)通过当前 Bean,获取能否拦截的切面
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != null) {
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;
}
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 通过代理工厂创建代理对象
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 为代理工厂设置额外功能
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
// 为代理工厂设置原始对象
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
// 冻结所有的配置
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 根据现有的工厂策略创建代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}
// ...
}
这里的代码我就不再详细说了,很多的东西和 AOP 创建代理的过程都是共用的。可以详看这篇文章:《揭秘AnnotationAwareAspectJAutoProxyCreator:Spring AOP自动代理的幕后英雄-CSDN博客》。
整个 Spring AOP 寻找切面、通知的过程就是 postProcessBeforeInstantiation 方法的功劳,而生成 AOP 代理对象就是 postProcessAfterInitialization 的功劳。而这些寻找切面、生成代理对象的功能其实是抽象父类 AbstractAutoProxyCreator 的功能。因此,InfrastructureAdvisorAutoProxyCreator 具备了寻找切面、通知以及生成代理对象的功能。
ProxyTransactionManagementConfiguration
这个类本身就是一个配置类,用于给容器中注册事务增强器,包括切入点的规则和额外功能。
@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
// 这个方法是核心方法
@Bean(name = {"org.springframework.transaction.config.internalTransactionAdvisor"})
@Role(2)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
// 创建事务增强器(切面)
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
// 内部维护了事务相关的属性源,向事务增强器中注入属性解析器
advisor.setTransactionAttributeSource(this.transactionAttributeSource());
// 注入执行事务时的拦截器,后续会依赖这个拦截器来开启、提交/回滚事务
// 当调用拥有事务的方法时,最终会调用到此拦截器内部的 invoke 方法
advisor.setAdvice(this.transactionInterceptor());
if (this.enableTx != null) {
advisor.setOrder((Integer)this.enableTx.getNumber("order"));
}
return advisor;
}
// 这个方法就是为第一个方法准备对象,作为前提条件,解析切入点,对 @Transactional 的解析
@Bean
@Role(2)
public TransactionAttributeSource transactionAttributeSource() {
// 创建事务属性源
return new AnnotationTransactionAttributeSource();
}
// 这个方法就是为第一个方法准备对象,作为前提条件,创建额外功能 TransactionInterceptor
@Bean
@Role(2)
public TransactionInterceptor transactionInterceptor() {
// 创建事务拦截器
TransactionInterceptor interceptor = new TransactionInterceptor();
// 关联事务属性
interceptor.setTransactionAttributeSource(this.transactionAttributeSource());
if (this.txManager != null) {
// 关联事务管理器
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
这种切入点的表现形式?其实就是以事务属性来约束,@Transactional 注解。具体我们可以详细看一下上面的 transactionAttributeSource 方法创建的 AnnotationTransactionAttributeSource 类。
切入点处理 transactionAttributeSource
AnnotationTransactionAttributeSource
事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource 解析事务注解。
该事务属性源是一个全局的属性源,记录着 Spring 容器中所有的事务方法的事务信息,供事务管理器 TransactionManager 使用。
public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource implements Serializable {
public AnnotationTransactionAttributeSource() {
this(true);
}
public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
// 设置注解解析器
this.publicMethodsOnly = publicMethodsOnly;
if (!jta12Present && !ejb3Present) {
// 添加 Spring 的事务 @Transactional 注解解析器,这也是程序默认执行的逻辑
this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
} else {
this.annotationParsers = new LinkedHashSet(4);
// 这个是 Spring 对单机版事务的支持
this.annotationParsers.add(new SpringTransactionAnnotationParser());
if (jta12Present) {
// 这个是 Spring 对分布式事务 JTA 的支持
this.annotationParsers.add(new JtaTransactionAnnotationParser());
}
if (ejb3Present) {
// 这个是 Spring 对分布式事务 Ejb3 的支持
this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
}
}
}
// ...
}
SpringTransactionAnnotationParser
这个类用于解析 @Transactional 注解的各种事务属性,例如:隔离级别、传播行为、超时、异常等。
public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {
public TransactionAttribute parseTransactionAnnotation(Transactional ann) {
return parseTransactionAnnotation(AnnotationUtils.getAnnotationAttributes(ann, false, false));
}
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"));
// 回滚策略
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;
}
// ...
}
额外功能 transactionInterceptor
// 这个方法就是为第一个方法准备对象,作为前提条件,创建额外功能 TransactionInterceptor
@Bean
@Role(2)
public TransactionInterceptor transactionInterceptor() {
// 创建事务拦截器
TransactionInterceptor interceptor = new TransactionInterceptor();
// 关联事务属性
interceptor.setTransactionAttributeSource(this.transactionAttributeSource());
if (this.txManager != null) {
// 关联事务管理器
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
有了切面、额外功能,那么代理对象就可以正常的创建出来。
代理生效过程
代理的生效过程,我们最好就通过 Debug 的方式来学习了。
测试程序如下,完整的程序参考:《万字长文深入理解Spring事务管理:配置、实现与最佳实践_spring 事务管理器-CSDN博客》:
public class Main {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext("world.xuewei.transaction.annotation");
@Test
public void test() {
ILeaderService leaderService = applicationContext.getBean(ILeaderService.class);
Leader leader = new Leader();
leader.setCode("1002");
leader.setName("李四");
leader.setSex(1);
leader.setAge(45);
leaderService.addLeader1(leader);
}
}
通过之前 AOP 的学习,我们知道,执行 leaderService.addLeader1(leader);
的时候会进入代理处理的 invoke 方法中(如果是 JDK 的话)。
通过代理的程序流转,会取依次执行目标对象的所有切面,而我们事务的切面(拦截器)也在其中。
之后就会执行 TransactionInterceptor 的 invoke 方法。
TransactionInterceptor
事务拦截器 TransactionInterceptor 保存了事务属性信息,事务管理器,并且实现了 MethodInterceptor,在目标方法执行的时候执行拦截器链(事务拦截器)。
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
// ...
@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
}
TransactionAspectSupport
invokeWithinTransaction 是 具体执行事务的方法,这里是整个事务生效的核心方法!
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);
// 获取配置的事务管理器对象(TransactionManager 事务管理器)
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
// 获取切入点的唯一标识:类名 + 方法名
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// 开启事务!创建事务信息 TransactionInfo
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
// 执行被增强的原始方法
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// 异常回滚!会获取事务管理器,执行回滚操作
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
// 清除事务信息,恢复线程私有的老的事务信息
cleanupTransactionInfo(txInfo);
}
// 提交事务!会获取事务管理器,执行事务提交操作
commitTransactionAfterReturning(txInfo);
return retVal;
}
else {
// 这个分支通常是不会进入的!
// ...
}
事务属性控制
隔离级别、超时时间、只读,这三个属性都不是 Spring 提供的,而是 JDBC 的规范决定,由各类数据库驱动去实现。
Connection connection = null;
connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
connection.setNetworkTimeout();
connection.setReadOnly(true);
异常的处理是由 Spring 实现,其实也比较好实现,因为 Spring 直接就可以使用 try 来捕获,之后按照不同的策略进行处理即可。
事务的传播行为也是由 Spring 来处理,这个是要复杂些,下一篇文章,我们重点分析事务的传播行为。