spring是如何实现声明式事务的

网友投稿 253 2022-10-28


spring是如何实现声明式事务的

前言

今天我们来讲讲spring的声明式事务。

开始

说到声明式事务,我们现在回顾一下事务这个概念,什么是事务呢,事务指的是逻辑上的⼀组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功。从而确保了数据的准确与安全。事务有着四大特性(ACID),分别是

原子性(Atomicity)原⼦性是指事务是⼀个不可分割的⼯作单位,事务中的操作要么都发⽣,要么都不发⽣。

⼀致性(Consistency)事务必须使数据库从⼀个⼀致性状态变换到另外⼀个⼀致性状态。

隔离性(Isolation)事务的隔离性是多个⽤户并发访问数据库时,数据库为每⼀个⽤户开启的事务,每个事务不能被其他事务的操作数据所⼲扰,多个并发事务之间要相互隔离。

持久性(Durability) 持久性是指⼀个事务⼀旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发⽣故障

也不应该对其有任何影响。

在spring中,一共有两种方式可以实现事务控制,分别是编程式事务和声明式事务。编程式事务指的是在代码中添加事务控制代码,而声明式事务指的是利用xml或者注解的形式来配置控制事务,下面就以纯注解配置声明式事务为例进行剖析。

spring开启声明式事务的注解是@EnableTransactionManagement,讲到这里首先要明白一点,spring的事务管理器管理事务其实就是利用aop的方式,通过创建动态代理加上拦截,实现的事务管理。在spring的配置类中加上这个注解,就支持了声明式事务,那么spring是怎么通过这么一个注解就可以支持事务的呢,我们来看代码。

首先我们看到,在这个注解上,import了一个selector

@Import(TransactionManagementConfigurationSelector.class)

我们看这个selector类中的这么一段代码

@Override

protected String[] selectImports(AdviceMode adviceMode) {

switch (adviceMode) {

case PROXY:

return new String[] {AutoProxyRegistrar.class.getName(),

ProxyTransactionManagementConfiguration.class.getName()};

case ASPECTJ:

return new String[] {determineTransactionAspectClass()};

default:

return null;

}

}

这段代码中,引入了AutoProxyRegistrar和ProxyTransactionManagementConfiguration这两个类,我们先来看AutoProxyRegistrar这个类,这个类中有一段这样的代码

if (mode == AdviceMode.PROXY) {

//重要的是这句代码

AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);

if ((Boolean) proxyTargetClass) {

AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);

return;

}

}

//我们进到这个方法中

@Nullable

public static BeanDefinition registerAutoProxyCreatorIfNecessary(

BeanDefinitionRegistry registry, @Nullable Object source) {

//可以看到引入了InfrastructureAdvisorAutoProxyCreator这个类,那么这个类又是什么呢

return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);

}

//先看一下

public class InfrastructureAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {

@Nullable

private ConfigurableListableBeanFactory beanFactory;

@Override

protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {

super.initBeanFactory(beanFactory);

this.beanFactory = beanFactory;

}

@Override

protected boolean isEligibleAdvisorBean(String beanName) {

return (this.beanFactory != null && this.beanFactory.containsBeanDefinition(beanName) &&

this.beanFactory.getBeanDefinition(beanName).getRole() == BeanDefinition.ROLE_INFRASTRUCTURE);

}

}

看一下继承结构图

可以看到这个方法间接继承于SmartInstantiationAwareBeanPostProcessor,最终继承于BeanPostProcessor,这说明InfrastructureAdvisorAutoProxyCreator类是一个后置处理器,并且跟 spring AOP 开启@EnableAspectJAutoProxy 时注册的AnnotationAwareAspectJProxyCreator实现的是同⼀个接口,这也对应了我之前所说声明式事务是springAOP思想的一种应用。

然后我们回过头来再看ProxyTransactionManagementConfiguration这个类,我们看到其中有一个事务增强器,一个属性解析器和是一个事务拦截器

@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)

@Role(BeanDefinition.ROLE_INFRASTRUCTURE)

public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(

TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {

// 事务增强器

BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();

// 注入属性解析器

advisor.setTransactionAttributeSource(transactionAttributeSource);

// 注入事务拦截器

advisor.setAdvice(transactionInterceptor);

if (this.enableTx != null) {

advisor.setOrder(this.enableTx.getNumber("order"));

}

return advisor;

}

@Bean

@Role(BeanDefinition.ROLE_INFRASTRUCTURE)

// 属性解析器

public TransactionAttributeSource transactionAttributeSource() {

return new AnnotationTransactionAttributeSource();

}

@Bean

@Role(BeanDefinition.ROLE_INFRASTRUCTURE)

// 事务拦截器

public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {

TransactionInterceptor interceptor = new TransactionInterceptor();

interceptor.setTransactionAttributeSource(transactionAttributeSource);

if (this.txManager != null) {

interceptor.setTransactionManager(this.txManager);

}

return interceptor;

}

先看看属性解析器

//注解解析器集合

private final Set annotationParsers;

这是一个注解解析器的集合,可以添加多种注解解析器,在这里我们主要关注的是spring事务注解解析器SpringTransactionParser,看一下相关代码

protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {

RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();

// 对应Transaction注解的相关属性

Propagation propagation = attributes.getEnum("propagation");

rbta.setPropagationBehavior(propagation.value());

Isolation isolation = attributeCyaGes.getEnum("isolation");

rbta.setIsolationLevel(isolation.value());

rbta.setTimeout(attributes.getNumber("timeout").intValue());

rbta.setReadOnly(attributes.getBoolean("readOnly"));

rbta.setQualifier(attributes.getString("value"));

List 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;

}

可以看到这段代码中的Enum和ClassArray其实正是@Transaction注解中的相关属性,这个属性解析器的作用之一就是用来解析@Transaction注解中的属性

看完了属性解析器,我们接下来看事务拦截器TransactionInterceptor,其中重要的是这段代码

@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);

}

然后我们进到这个方法里面

@Nullable

protected Object invokeWithinTransaction(Method method, @Nullable Class> targetClass,

final InvocationCallback invocation) throws Throwable {

// If the transaction attribute is null, the method is non-transactional.

// 获取属性解析器,在配置类ProxyTransactionManagementConfiguration配置时加入

TransactionAttributeSource tas = getTransactionAttributeSource();

final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);

final TransactionManager tm = determineTransactionManager(txAttr);

if (this.reactiveAdapterRegistrCyaGey != null && tm instanceof ReactiveTransactionManager) {

ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {

if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && KotlinDelegate.isSuspend(method)) {

throw new TransactionUsageException(

"Unsupported annotated transaction on suspending function detected: " + method +

". Use TransactionalOperator.transactional extensions instead.");

}

ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(method.getReturnType());

if (adapter == null) {

throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " +

method.getReturnType());

}

return new ReactiveTransactionSupport(adapter);

});

return txSupport.invokeWithinTransaction(

method, targetClass, invocation, txAttr, (ReactiveTransactionManager) tm);

}

// 获取事务管理器

PlatformTransactionManager ptm = asPlatformTransactionManager(tm);

final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {

// Standard transaction demarcation with getTransaction and commit/rollback calls.

TransactionInfo txInfo = createTransactionIfNecessary(ptm, 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

// 目标方法抛异常,会执行回滚的操作

completeTransactionAfterThrowing(txInfo, ex);

throw ex;

}

finally {

cleanupTransactionInfo(txInfo);

}

if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {

// Set rollback-only in case of Vavr failure matching our rollback rules...

TransactionStatus status = txInfo.getTransactionStatus();

if (status != null && txAttr != null) {

retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);

}

}

// 目标方法正常运行,会执行commitTransactionAfterReturning,执行事务提交操作

commitTransactionAfterReturning(txInfo);

return retVal;

}

else {

final ThrowableHolder throwableHolder = new ThrowableHolder();

// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.

try {

Object result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {

TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);

try {

Object retVal = invocation.proceedWithInvocation();

if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {

// Set rollback-only in case of Vavr failure matching our rollback rules...

retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);

}

return retVal;

}

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);

http:// }

throw ex2;

}

catch (Throwable ex2) {

if (throwableHolder.throwable != null) {

logger.error("Application exception overridden by commit exception", throwableHolder.throwable);

}

throw ex2;

}

}

}

总结

总体来说,spring实现声明式事务的过程是这样的

@EnableTransactionManagement 注解,通过@import引⼊了TransactionManagementConfigurationSelector类,它的selectImports⽅法导⼊了另外两个类:AutoProxyRegistrar和ProxyTransactionManagementConfiguration

AutoProxyRegistrar类中方法registerBeanDefinitions中,通过 AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)引⼊InfrastructureAdvisorAutoProxyCreator,是一个后置处理器类

ProxyTransactionManagementConfiguration 是⼀个添加了@Configuration注解的配置类,注册了事务增强器(注⼊属性解析器、事务拦截器)AnnotationTransactionAttributeSource和TransactionInterceptor,AnnotationTransactionAttributeSource内部持有了⼀个解析器集合 Set annotationParsers,具体使⽤的是SpringTransactionAnnotationParser解析器,用来解析@Transactional的事务属性,事务拦截器TransactionInterceptor实现了MethodInterceptor接⼝,该通用拦截会在产⽣代理对象之前和aop增强合并,最终⼀起影响到代理对象,TransactionInterceptor的invoke⽅法中invokeWithinTransaction会触发原有业务逻辑调用(增强事务)


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:shell脚本练习(12.12)
下一篇:shell脚本练习(12.11)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~