Spring事务处理原理步骤详解

网友投稿 296 2022-12-11


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、事务处理原理http://

原理分析:

* 原理:

* 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) {

AnnotationAFfxysALsttributes 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类的作用类似。

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

http:// 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;

}

}

}


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

上一篇:Java5种遍历HashMap数据的写法
下一篇:Spring容器注册组件实现过程解析
相关文章

 发表评论

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