【spring 注解驱动开发】spring事务处理原理
阅读原文时间:2023年07月10日阅读:2

尚学堂spring 注解驱动开发学习笔记之 - 事务处理

事务处理

1、事务处理实现

实现步骤:

* 声明式事务:
*
* 环境搭建:
* 1、导入相关依赖
* 数据源、数据库驱动、Spring-jdbc模块
* 2、配置数据源、JdbcTemplate(Spring提供的简化数据库操作的工具)操作数据
* 3、给方法上标注 @Transactional 表示当前方法是一个事务方法;
* 4、 @EnableTransactionManagement 开启基于注解的事务管理功能;
* @EnableXXX
* 5、配置事务管理器来控制事务;
* @Bean
* public PlatformTransactionManager transactionManager()

代码实现:

@EnableTransactionManagement
@ComponentScan("com.atguigu.tx")
@Configuration
public class TxConfig {

//数据源  
@Bean  
public DataSource dataSource() throws Exception{  
    ComboPooledDataSource dataSource = new ComboPooledDataSource();  
    dataSource.setUser("root");  
    dataSource.setPassword("123456");  
    dataSource.setDriverClass("com.mysql.jdbc.Driver");  
    dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");  
    return dataSource;  
}

@Bean  
public JdbcTemplate jdbcTemplate() throws Exception{  
    //Spring对@Configuration类会特殊处理;给容器中加组件的方法,多次调用都只是从容器中找组件  
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource());  
    return jdbcTemplate;  
}

//注册事务管理器在容器中  
@Bean  
public PlatformTransactionManager transactionManager() throws Exception{  
    return new DataSourceTransactionManager(dataSource());  
}  

} 

2、事务处理原理

原理分析:

* 原理:
* 1)、@EnableTransactionManagement
* 利用TransactionManagementConfigurationSelector给容器中会导入组件
* 导入两个组件
* AutoProxyRegistrar
* ProxyTransactionManagementConfiguration
* 2)、AutoProxyRegistrar:
* 给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件;
* InfrastructureAdvisorAutoProxyCreator:?
* 利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用;
*
* 3)、ProxyTransactionManagementConfiguration 做了什么?
* 1、给容器中注册事务增强器;
* 1)、事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource解析事务注解
* 2)、事务拦截器:
* TransactionInterceptor;保存了事务属性信息,事务管理器;
* 他是一个 MethodInterceptor;
* 在目标方法执行的时候;
* 执行拦截器链;
* 事务拦截器:
* 1)、先获取事务相关的属性
* 2)、再获取PlatformTransactionManager,如果事先没有添加指定任何transactionmanger
* 最终会从容器中按照类型获取一个PlatformTransactionManager;
* 3)、执行目标方法
* 如果异常,获取到事务管理器,利用事务管理回滚操作;
* 如果正常,利用事务管理器,提交事务
*
*/

核心代码

1、EnableTransactionManagement注解,注入TransactionManagementConfigurationSelector类

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {

2、TransactionManagementConfigurationSelector类,最终会导入AutoProxyRegistrar.class和ProxyTransactionManagementConfiguration.class两个组件。

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector {

/\*\*  
 \* Returns {@link ProxyTransactionManagementConfiguration} or  
 \* {@code AspectJ(Jta)TransactionManagementConfiguration} for {@code PROXY}  
 \* and {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()},  
 \* respectively.  
 \*/  
@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;  
    }  
}

private String determineTransactionAspectClass() {  
    return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?  
            TransactionManagementConfigUtils.JTA\_TRANSACTION\_ASPECT\_CONFIGURATION\_CLASS\_NAME :  
            TransactionManagementConfigUtils.TRANSACTION\_ASPECT\_CONFIGURATION\_CLASS\_NAME);  
}

}

3、AutoProxyRegistrar类的作用为:

  给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件;

  最终的目的是:利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用;

@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
Set annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
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()) {
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));
}
}

InfrastructureAdvisorAutoProxyCreator类的作用与AnnotationAwareAspectJAutoProxyCreator类的作用类似。可参考:【spring 注解驱动开发】Spring AOP原理

@SuppressWarnings("serial")
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

4、ProxyTransactionManagementConfiguration类

代理事务管理配置类

@Configuration
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());  
    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;  
}

}

TransactionInterceptor类,事务调用:invokeWithinTransaction()方法为最终执行的方法

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

TransactionAspectSupport类的最终事务方法执行:

@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.  
    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;  
        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;  
        }  
    }  
}