Spring笔记(5)

一.背景

  前面详解了实现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;
                }
            }
        } 
原文地址:https://www.cnblogs.com/huangrenhui/p/13849553.html