springboot如何开启事务@Transactional

客官°小女子只卖身不卖艺 2022-10-16 04:48 194阅读 0赞

在这里插入图片描述

上图展示了springboot事务管理器实现的一个结构图,直接使用的是JdbcTransactionManager事务管理器,spring的核心接口是PlatformTransactionManager;

一、通过自动化配置类TransactionAutoConfiguration启动spring事务
  1. @Configuration(proxyBeanMethods = false)
  2. @ConditionalOnBean(TransactionManager.class)
  3. @ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
  4. public static class EnableTransactionManagementConfiguration {
  5. @Configuration(proxyBeanMethods = false)
  6. @EnableTransactionManagement(proxyTargetClass = false)
  7. @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",
  8. matchIfMissing = false)
  9. public static class JdkDynamicAutoProxyConfiguration {
  10. }
  11. @Configuration(proxyBeanMethods = false)
  12. @EnableTransactionManagement(proxyTargetClass = true)
  13. @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
  14. matchIfMissing = true)
  15. public static class CglibAutoProxyConfiguration {
  16. }
  17. }
  • 默认使用Cglib动态代理
  • 可以通过spring.aop.proxy-target-class配置修改默认代理方式
  • 通过@EnableTransactionManagement注解开启事务模式
二、EnableTransactionManagement注解将TransactionManagementConfigurationSelector注入容器
  1. @Target(ElementType.TYPE)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. @Import(TransactionManagementConfigurationSelector.class)
  5. public @interface EnableTransactionManagement {
  6. boolean proxyTargetClass() default false;
  7. AdviceMode mode() default AdviceMode.PROXY;
  8. int order() default Ordered.LOWEST_PRECEDENCE;
  9. }
  • 代理模式默认是JDK动态代理模式
  • 切面的优先级最低
  • 将TransactionManagementConfigurationSelector类注入到容器之中
三、TransactionManagementConfigurationSelector类
  1. public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
  2. /** * Returns {@link ProxyTransactionManagementConfiguration} or * {@code AspectJ(Jta)TransactionManagementConfiguration} for {@code PROXY} * and {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()}, * respectively. */
  3. @Override
  4. protected String[] selectImports(AdviceMode adviceMode) {
  5. switch (adviceMode) {
  6. case PROXY:
  7. return new String[] { AutoProxyRegistrar.class.getName(),
  8. ProxyTransactionManagementConfiguration.class.getName()};
  9. case ASPECTJ:
  10. return new String[] { determineTransactionAspectClass()};
  11. default:
  12. return null;
  13. }
  14. }
  15. private String determineTransactionAspectClass() {
  16. return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
  17. TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
  18. TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
  19. }
  20. }

默认会将AutoProxyRegistrar和ProxyTransactionManagementConfiguration注入到IOC容器之中;

四、ProxyTransactionManagementConfiguration会实例化TransactionInterceptor切面拦截器,并配置切面及切点
  1. @Bean
  2. @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  3. public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
  4. TransactionInterceptor interceptor = new TransactionInterceptor();
  5. interceptor.setTransactionAttributeSource(transactionAttributeSource);
  6. if (this.txManager != null) {
  7. interceptor.setTransactionManager(this.txManager);
  8. }
  9. return interceptor;
  10. }

将TransactionInterceptor切面拦截器注入到IOC容器;

  1. @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
  2. @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  3. public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
  4. TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
  5. BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
  6. advisor.setTransactionAttributeSource(transactionAttributeSource);
  7. advisor.setAdvice(transactionInterceptor);
  8. if (this.enableTx != null) {
  9. advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
  10. }
  11. return advisor;
  12. }

将拦截器织入到springboot约定AOP流程中,然后通过@Transactional注解标注的方法就会被织入到约定好的流程之中;

其中TransactionInterceptor拦截器的核心是invoke方法,事物的开启、连接点、织入、事物回滚、事物关闭都是在这个方法搞定;
  1. @Override
  2. @Nullable
  3. public Object invoke(MethodInvocation invocation) throws Throwable {
  4. // Work out the target class: may be {@code null}.
  5. // The TransactionAttributeSource should be passed the target class
  6. // as well as the method, which may be from an interface.
  7. Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
  8. // Adapt to TransactionAspectSupport's invokeWithinTransaction...
  9. return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() {
  10. @Override
  11. @Nullable
  12. public Object proceedWithInvocation() throws Throwable {
  13. return invocation.proceed();
  14. }
  15. @Override
  16. public Object getTarget() {
  17. return invocation.getThis();
  18. }
  19. @Override
  20. public Object[] getArguments() {
  21. return invocation.getArguments();
  22. }
  23. });
  24. }

发表评论

表情:
评论列表 (有 0 条评论,194人围观)

还没有评论,来说两句吧...

相关阅读

    相关 SpringBoot开启事务

    @Transactional 直接在想要启动事务的方法或者类上添加@Transactional注解即可,在类上添加注解,默认类下的所有方法都会使用事务。 在类上添加注解