Spring笔记(5) - 声明式事务@EnableTransactionManagement注解源码分析

本文详细介绍了Spring框架中使用注解实现事务管理的方法,包括配置类的定义、业务代码的编写及异常处理机制。通过具体示例展示了如何利用@EnableTransactionManagement开启基于注解的事务管理,并解析了其内部原理。
摘要由CSDN通过智能技术生成

一.背景

  前面详解了实现Spring事务的两种方式的不同实现:编程式事务和声明式事务,对于配置都使用到了xml配置,今天介绍Spring事务的注解开发,例如下面例子:

  1. 配置类:注册数据源、JDBC模板、事务管理器
    //包扫描,将包下的dao、service注册到Spring容器中
    @ComponentScan("com.hrh")
    //开启基于注解的事务管理,跟@Transactional注解配套使用
    @EnableTransactionManagement
    //表明TxConfig是配置类
    @Configuration
    public class TxConfig {
        //注册数据源
        @Bean
        public DataSource dataSource() throws Exception {
            ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
            comboPooledDataSource.setUser("xxx");
            comboPooledDataSource.setPassword("xxx");
            comboPooledDataSource.setJdbcUrl("jdbc:mysql://xxx:3306/xxx");
            comboPooledDataSource.setDriverClass("com.mysql.jdbc.Driver");
            return comboPooledDataSource;
        }
    
        //注册jdbc模板
        @Bean
        public JdbcTemplate jdbcTemplate() throws Exception {
            return new JdbcTemplate(dataSource());
        }
    
        //注册事务管理器来控制事务
        @Bean
        public PlatformTransactionManager manager() throws Exception {
            return new DataSourceTransactionManager(dataSource());
        }
    }
  2. 业务代码:
    @Repository
    public class UserDao {
        @Autowired
        private JdbcTemplate jdbcTemplate;
        public void insert(){
            String sql ="insert into tab_person(name,age) values(?,?)";
            String name = UUID.randomUUID().toString().substring(0, 5);
            jdbcTemplate.update(sql,name,19);
        }
    }
    
    @Service
    public class UserService{
        @Autowired
        private UserDao userDao;
        
        //添加事务
        @Transactional
        public void insert() {
            userDao.insert();
            System.out.println("插入完成。");
            int i = 10/0;
        }
    }
  3. 测试:从下面运行结果可以看出抛出了异常,在数据库中查看数据发现没有最新的数据插入,表明插入操作进行了回滚
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TxConfig.class);
            UserService bean = context.getBean(UserService.class);
            bean.insert();
            context.close();
        }
        
    运行结果:
        
        插入完成。
        Exception in thread "main" java.lang.ArithmeticException: / by zero
            at com.hrh.service.UserService.insert(UserService.java:20) 

 二. @EnableTransactionManagement注解源码分析

  1.流程

  1. EnableTransactionManagement导入一个TransactionManagementConfigurationSelector组件
  2. TransactionManagementConfigurationSelector默认导入两个组件:AutoProxyRegistrar和ProxyTransactionManagementConfiguration

  3. AutoProxyRegistrar(利用后置处理器包装代理对象):注册一个InfrastructureAdvisorAutoProxyCreator组件(自动代理创建器),利用后置处理器机制在对象创建之后包装对象,返回一个代理对象(增强器),利用拦截器链执行方法

  4. ProxyTransactionManagementConfiguration(注册配置):给容器注册各种组件,注册了事务增强器

        4.1)事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource解析了注解上的各种属性信息

        4.2)同时用到TransactionInterceptor事务拦截器:保存了事务属性信息、事务管理器

          4.2.1)在目标方法执行时:执行拦截器链(即TransactionInterceptor)

            4.2.2)TransactionInterceptor事务拦截器的作用:获取事务相关的属性,再获取事务管理器进行事务的执行、回滚或提交操作;

  2.源码解析

  1.  EnableTransactionManagement导入一个TransactionManagementConfigurationSelector组件
    @Import({TransactionManagementConfigurationSelector.class})
    public @interface EnableTransactionManagement {
        //默认为false
        boolean proxyTargetClass() default false;
        //默认为PROXY
        AdviceMode mode() default AdviceMode.PROXY;
    
        int order() default 2147483647;
    }

     

  2. TransactionManagementConfigurationSelector默认导入两个组件:AutoProxyRegistrar和ProxyTransactionManagementConfiguration
    public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
        //AdviceMode值在EnableTransactionManagement默认了
        @Override
        protected String[] selectImports(AdviceMode adviceMode) {
            switch (adviceMode) {
                case PROXY:
                    return new String[] {AutoProxyRegistrar.class.getName(),
                            ProxyTransactionManagementConfiguration.class.getName()};
                case ASPECTJ:
                    return new String[] {
                            TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
                default:
                    return null;
            }
        }
    
    }
  3. AutoProxyRegistrar(利用后置处理器包装代理对象):注册一个InfrastructureAdvisorAutoProxyCreator组件(自动代理创建器),利用后置处理器机制在对象创建之后包装对象,返回一个代理对象(增强器),利用拦截器链执行方法
    public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            boolean candidateFound = false;
            Set<String> 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;
                    //注册一个InfrastructureAdvisorAutoProxyCreator组件(自动代理创建器)
                    if (mode == AdviceMode.PROXY) {
                        AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
                        //proxyTargetClass在EnableTransactionManagement默认false
                        if ((Boolean) proxyTargetClass) {
                            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
                            return;
                        }
                    }
                }
            }
            .....
        }
    
    }
    • AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry):自动代理创建器
      public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
              return registerAutoProxyCreatorIfNecessary(registry, null);
          }
      
          @Nullable
          public static BeanDefinition registerAutoProxyCreatorIfNecessary(
                  BeanDefinitionRegistry registry, @Nullable Object source) {
              //给容器注册InfrastructureAdvisorAutoProxyCreator(是一个后置处理器),利用后置处理器机制在对象创建之后包装对象,返回一个代理对象(增强器),利用拦截器链执行方法
              return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
          }
  4. ProxyTransactionManagementConfiguration(注册配置):给容器注册各种组件,注册了事务增强器
    @Configuration
    public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
        //注册事务增强器BeanFactoryTransactionAttributeSourceAdvisor
        @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
        @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
        public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
            BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
            //设置事务属性,从注解解析器获取注解上的事务属性值
            advisor.setTransactionAttributeSource(transactionAttributeSource());
            //设置了TransactionInterceptor事务拦截器
            advisor.setAdvice(transactionInterceptor());
            advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
            return advisor;
        }
        //注册事务属性,解析注解中的各种属性,比如propagation、isolation、timeout等
        @Bean
        @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
        public TransactionAttributeSource transactionAttributeSource() {
            //注解解析器
            return new AnnotationTransactionAttributeSource();
        }
        //注册了TransactionInterceptor事务拦截器:保存了事务属性信息、事务管理器
        @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;
        }
    
    }
    1. 注解解析器AnnotationTransactionAttributeSource
      public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
          this.publicMethodsOnly = publicMethodsOnly;
          this.annotationParsers = new LinkedHashSet<TransactionAnnotationParser>(4);
          //添加spring事务注解的解析器
          this.annotationParsers.add(new SpringTransactionAnnotationParser());
          if (jta12Present) {
              //添加jta事务注解的解析器
              this.annotationParsers.add(new JtaTransactionAnnotationParser());
          }
          if (ejb3Present) {
              //添加Ejb3事务注解的解析器
              this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
          }
      }
      public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
          AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(
                  element, Transactional.class);
          if (attributes != null) {
              //解析注解
              return parseTransactionAnnotation(attributes);
          }
          else {
              return null;
          }
      }
      //解析注解Transactional上的每个属性
      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<RollbackRuleAttribute>();
          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;
      }
    2. 事务拦截器TransactionInterceptor:是一个MethodInterceptor,方法拦截器(4个通知方法整合成了增强器,增强器整合成了MethodInterceptor。我们在容器中放置了一个代理对象,当要执行代理对象时,方法拦截器就执行了)
      public Object invoke(final 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, new InvocationCallback() {
              @Override
              public Object proceedWithInvocation() throws Throwable {
                  return invocation.proceed();
              }
          });
      }
      protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
              throws Throwable {
      
          // If the transaction attribute is null, the method is non-transactional.
          //获取事务属性
          final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
          //获取事务管理器
          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 = null;
              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,
                          new TransactionCallback<Object>() {
                              @Override
                              public Object doInTransaction(TransactionStatus 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;
              }
          }
      } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值