zoukankan      html  css  js  c++  java
  • spring注解开发-声明式事务(源码)

    1. 环境搭建与测试

    1)导入相关依赖

    数据源、数据库驱动、Spring-jdbc模块

            <dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-jdbc</artifactId>
    			<version>4.3.12.RELEASE</version>
    		</dependency>
            <dependency>
    			<groupId>c3p0</groupId>
    			<artifactId>c3p0</artifactId>
    			<version>0.9.1.2</version>
    		</dependency>
            <dependency>
    			<groupId>mysql</groupId>
    			<artifactId>mysql-connector-java</artifactId>
    			<version>5.1.44</version>
    		</dependency>
    
    2)配置数据源、JdbcTemplate 操作数据
       //数据源
    	@Bean
    	public DataSource dataSource() throws Exception{
    		ComboPooledDataSource dataSource = new ComboPooledDataSource();
    		dataSource.setUser("root");
    		dataSource.setPassword("1111");
    		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;
    	}
    
    3)给方法上标注@Transactional表示当前方法是一个事务方法;
    @Transactional
    	public void insertUser(){
    		userDao.insert();
    		//otherDao.other();
    		System.out.println("插入完成...");
    		int i = 10/0;
    	}
    
    4)@EnableTransactionManagement开启基于注解的事务管理功能;
    5)配置事务管理器来控制事务;
        @Bean
    	public PlatformTransactionManager transactionManager() throws Exception{
    		return new DataSourceTransactionManager(dataSource());
    	}
    

    2. 原理分析

    1)@EnableTransactionManagement利用TransactionManagementConfigurationSelector给容器中会导入组件;adviceMode默认是proxy,因此会导入两个组件AutoProxyRegistrar,ProxyTransactionManagementConfiguration

    下面不是完整的类代码,只是源码中的片段整合而来,相应的类名在注释中
    //EnableTransactionManagement
    AdviceMode mode() default AdviceMode.PROXY;
    
    //TransactionManagementConfigurationSelector
    case PROXY:
                return new String[]{AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
                
    

    2)AutoProxyRegistrar:给容器中注册一个InfrastructureAdvisorAutoProxyCreator 组件;

    //AopConfigUtils类
    public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
            return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
        }
    

    InfrastructureAdvisorAutoProxyCreator: 利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用;----同AOP;
    InfrastructureAdvisorAutoProxyCreator的UML图例
    logical RDD 转换成 physical stage

    3)ProxyTransactionManagementConfiguration 做了什么?

    1>给容器中注册事务增强器;

    1.1>事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource解析事务注解

        //ProxyTransactionManagementConfiguration
        @Bean
        @Role(2)
        public TransactionAttributeSource transactionAttributeSource() {
            return new AnnotationTransactionAttributeSource();
        }
        
        //AnnotationTransactionAttributeSource
        public AnnotationTransactionAttributeSource(TransactionAnnotationParser annotationParser) {
            this.publicMethodsOnly = true;
            Assert.notNull(annotationParser, "TransactionAnnotationParser must not be null");
            this.annotationParsers = Collections.singleton(annotationParser);
        }
    

    1.2>事务拦截器:TransactionInterceptor;保存了事务属性信息,事务管理器;他是一个MethodInterceptor;在目标方法执行的时候;执行拦截器链;事务拦截器:

    //ProxyTransactionManagementConfiguration
    @Bean
        @Role(2)
        public TransactionInterceptor transactionInterceptor() {
            TransactionInterceptor interceptor = new TransactionInterceptor();
            interceptor.setTransactionAttributeSource(this.transactionAttributeSource());
            if (this.txManager != null) {
                interceptor.setTransactionManager(this.txManager);
            }
            return interceptor;
        }
    

    1.2.1>先获取事务相关的属性

    //TransactionAspectSupport
    protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final TransactionAspectSupport.InvocationCallback invocation) throws Throwable {
            final TransactionAttribute txAttr = this.getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
    

    1.2.2>再获取PlatformTransactionManager,如果事先没有添加指定任何transactionmanger,最终会从容器中按照类型获取一个PlatformTransactionManager;

    //TransactionAspectSupport->invokeWithinTransaction
    final PlatformTransactionManager tm = this.determineTransactionManager(txAttr);
    //上面的方法
    protected PlatformTransactionManager determineTransactionManager(TransactionAttribute txAttr) {
            if (txAttr != null && this.beanFactory != null) {
                String qualifier = txAttr.getQualifier();
                if (StringUtils.hasText(qualifier)) {
                    return this.determineQualifiedTransactionManager(qualifier);
                } else if (StringUtils.hasText(this.transactionManagerBeanName)) {
                    return this.determineQualifiedTransactionManager(this.transactionManagerBeanName);
                } else {
                    PlatformTransactionManager defaultTransactionManager = this.getTransactionManager();
                    if (defaultTransactionManager == null) {
                        defaultTransactionManager = (PlatformTransactionManager)this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
                        if (defaultTransactionManager == null) {
                            defaultTransactionManager = (PlatformTransactionManager)this.beanFactory.getBean(PlatformTransactionManager.class);
                            this.transactionManagerCache.putIfAbsent(DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
                        }
                    }
    
                    return defaultTransactionManager;
                }
            } else {
                return this.getTransactionManager();
            }
        }
    

    1.2.3>执行目标方法;如果异常,获取到事务管理器,利用事务管理回滚操作;如果正常,利用事务管理器,提交事务

    //TransactionAspectSupport->invokeWithinTransaction
    protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final TransactionAspectSupport.InvocationCallback invocation) throws Throwable {
    //获取事务属性
            final TransactionAttribute txAttr = this.getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
    //事务管理器
            final PlatformTransactionManager tm = this.determineTransactionManager(txAttr);
            final String joinpointIdentification = this.methodIdentification(method, targetClass, txAttr);
            if (txAttr != null && tm instanceof CallbackPreferringPlatformTransactionManager) {
                try {
                    Object result = ((CallbackPreferringPlatformTransactionManager)tm).execute(txAttr, new TransactionCallback<Object>() {
                        public Object doInTransaction(TransactionStatus status) {
                            TransactionAspectSupport.TransactionInfo txInfo = TransactionAspectSupport.this.prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
    
                            TransactionAspectSupport.ThrowableHolder var4;
                            try {
                                Object var3 = invocation.proceedWithInvocation();
                                return var3;
                            } catch (Throwable var8) {
                                if (txAttr.rollbackOn(var8)) {
                                    if (var8 instanceof RuntimeException) {
                                        throw (RuntimeException)var8;
                                    }
    
                                    throw new TransactionAspectSupport.ThrowableHolderException(var8);
                                }
    
                                var4 = new TransactionAspectSupport.ThrowableHolder(var8);
                            } finally {
                                TransactionAspectSupport.this.cleanupTransactionInfo(txInfo);
                            }
    
                            return var4;
                        }
                    });
                    if (result instanceof TransactionAspectSupport.ThrowableHolder) {
                        throw ((TransactionAspectSupport.ThrowableHolder)result).getThrowable();
                    } else {
                        return result;
                    }
                } catch (TransactionAspectSupport.ThrowableHolderException var14) {
                    throw var14.getCause();
                }
            } else {
                TransactionAspectSupport.TransactionInfo txInfo = this.createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
                Object retVal = null;
    
                try {
                    retVal = invocation.proceedWithInvocation();
                } catch (Throwable var15) {
            //事务异常--执行回滚操作
              this.completeTransactionAfterThrowing(txInfo, var15);
                    throw var15;
                } finally {
                    this.cleanupTransactionInfo(txInfo);
                }
    //事务正常--执行commit
                this.commitTransactionAfterReturning(txInfo);
                return retVal;
            }
        }
    

    commit操作:

    //TransactionAspectSupport
    protected void commitTransactionAfterReturning(TransactionAspectSupport.TransactionInfo txInfo) {
            if (txInfo != null && txInfo.hasTransaction()) {
                if (this.logger.isTraceEnabled()) {
                    this.logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
                }
                txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
            }
        }
    

    rollback操作:

    //TransactionAspectSupport
    protected void completeTransactionAfterThrowing(TransactionAspectSupport.TransactionInfo txInfo, Throwable ex) {
            if (txInfo != null && txInfo.hasTransaction()) {
                if (this.logger.isTraceEnabled()) {
                    this.logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "] after exception: " + ex);
                }
    
                if (txInfo.transactionAttribute.rollbackOn(ex)) {
                    try {
                        txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
                    } catch (TransactionSystemException var7) {
                        this.logger.error("Application exception overridden by rollback exception", ex);
                        var7.initApplicationException(ex);
                        throw var7;
                    } catch (RuntimeException var8) {
                        this.logger.error("Application exception overridden by rollback exception", ex);
                        throw var8;
                    } catch (Error var9) {
                        this.logger.error("Application exception overridden by rollback error", ex);
                        throw var9;
                    }
                } else {
                    try {
                        txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
                    } catch (TransactionSystemException var4) {
                        this.logger.error("Application exception overridden by commit exception", ex);
                        var4.initApplicationException(ex);
                        throw var4;
                    } catch (RuntimeException var5) {
                        this.logger.error("Application exception overridden by commit exception", ex);
                        throw var5;
                    } catch (Error var6) {
                        this.logger.error("Application exception overridden by commit error", ex);
                        throw var6;
                    }
                }
            }
    
        }
    
  • 相关阅读:
    php改写session到数据库
    mysql UNIX时间戳与日期的相互转换
    关于netbeans中的JComboBox(复选框)
    Java中数据类型转换
    趣味游戏___表示数
    C语言 约瑟夫圈问题:N个人围成一圈,从第一个人开始按顺序报数并编号1,2,3,……N,然后开始从第一个人转圈报数,凡是报到3的退出圈子。则剩下的最后一个人编号是多少。
    maven——使用阿里云镜像
    spring——整合Mybatis
    spring——AOP(静态代理、动态代理、AOP)
    spring——通过注解显式的完成自动装配
  • 原文地址:https://www.cnblogs.com/ntbww93/p/10102310.html
Copyright © 2011-2022 走看看