zoukankan      html  css  js  c++  java
  • Spring声明式事物原理分析

     基础准备 pom 

    <project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.springannotation.test</groupId>
        <artifactId>NddSpring</artifactId>
        <version>1</version>
    
        <dependencies>
    
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>4.3.12.RELEASE</version>
            </dependency>
                <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
                <version>4.3.12.RELEASE</version>
            </dependency>
            
            <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>
    
            <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.44</version>
            </dependency>
        </dependencies>
    
    </project>

    基础准备 配置 

    package com.lkd.config;
    
    import javax.sql.DataSource;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.EnableAspectJAutoProxy;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    import com.lkd.aop.LogAspects;
    import com.lkd.aop.MathCalculator;
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
    
    @Configuration
    @EnableAspectJAutoProxy
    @ComponentScan("com.lkd")
    @EnableTransactionManagement
    public class AopConfig {
    	
    	@Bean
    	public MathCalculator calu() {
    		return new MathCalculator();
    	}
    	
    	@Bean
    	public LogAspects aspects() {
    		return new LogAspects();
    	}
    	@Bean
    	public Object obj() {
    		return new Object();
    	}
    	
    	@Bean
    	public DataSource student() throws Exception {
    		ComboPooledDataSource  student  =new ComboPooledDataSource();
    		student.setUser("root");
    		student.setPassword("123456");
    		//student.setDriverClass("com.mysql.jdbc.driver");
    		student.setDriverClass("com.mysql.jdbc.Driver");
    		student.setJdbcUrl("jdbc:mysql://localhost:3306/mytransction");
    		return student;
    	}
    	@Bean
    	public DataSource student2() throws Exception {
    		ComboPooledDataSource  student  =new ComboPooledDataSource();
    		student.setUser("root");
    		student.setPassword("123456");
    		//student.setDriverClass("com.mysql.jdbc.driver");
    		student.setDriverClass("com.mysql.jdbc.Driver");
    		student.setJdbcUrl("jdbc:mysql://localhost:3306/myt2");
    		return student;
    	}
    	
    	@Bean
    	public JdbcTemplate jdbcTemplate1(DataSource student) {
    		return new JdbcTemplate(student);
    	}
    	@Bean
    	public JdbcTemplate jdbcTemplate2(DataSource student2) {
    		return new JdbcTemplate(student2);
    	}
    	
    	@Bean
    	public MysqlDataSource student3() {
    		MysqlDataSource student = new MysqlDataSource();
    		student.setUser("root");
    		student.setPassword("123456");
    		//student.setDriverClass("com.mysql.jdbc.driver");
    		student.setURL("jdbc:mysql://localhost:3306/myt2");
    		return student;
    		
    	}
    	@Bean
    	public JdbcTemplate jdbcTemplate3(DataSource student3) {
    		return new JdbcTemplate(student3);
    	}
    	
    	@Bean
    	public PlatformTransactionManager txmanager() throws Exception {
    		return new DataSourceTransactionManager(student());
    	}
    }
    

      开始分析 

      @EnableTransactionManagement 开启声明式事务功能 

         为容器中导入TransactionManagementConfigurationSelector,它又会容器中导入 AutoProxyRegistrar(imp BeanDefinitionRegister)其作用为容器注入 InfrastructureAdvisorAutoProxyCreator 自动代理增强组件;利用后置处理器机制在对象创建以后

                                                                     包装对象返回一个代理对象;

                                             ProxyTransactionManagementConfiguration  给容器注入事物增强器 (解析注解) AnnotationTransactionAttributeSource;给容器中注入事物拦截器 TransactionInterceptor                                                                   ,保存了事物属性信息包括事务管理器

        a: 先获取事物属性TransactionAttribute,再获取PlatformTransactionManager平台事物管理器,未在Transctional注解中指定事物,则会在ioc容器中根据PlatFormTransctionManager类型的事物管理器对象

                                                                     

      

    public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
    
        /**
         * {@inheritDoc}
         * @return {@link ProxyTransactionManagementConfiguration} or
         * {@code AspectJTransactionManagementConfiguration} 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[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
                default:
                    return null;
            }
        }

      执行过程中出现异常

    	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;
    		}
    

      

        总结 : 事物实际上在spring维度是对AOP的应用,掌握了Aop原理,事物则会理解起来贼tm容易。如果AOP不清楚的可以看我Aop解析。

      https://www.cnblogs.com/leaveast/p/10829917.html

  • 相关阅读:
    monitor system
    monitor disk
    manage account
    windows
    backup daily
    shell 脚本编程概述
    OGNL表达式
    Struts2各个功能详解(2)-输入校验和拦截器
    struts2各个功能详解(1)----参数自动封装和类型自动转换
    Struts2源码解析2
  • 原文地址:https://www.cnblogs.com/leaveast/p/10845801.html
Copyright © 2011-2022 走看看