浅尝Spring注解开发_声明式事务及原理

浅尝Spring注解开发_声明式事务及原理

浅尝Spring注解开发,基于Spring 4.3.12
包含声明式事务使用、基本原理分析

浅尝Spring注解开发_自定义注册组件、属性赋值、自动装配
浅尝Spring注解开发_Bean生命周期及执行过程
浅尝Spring注解开发_AOP原理及完整过程分析(源码)
浅尝Spring注解开发_声明式事务及原理
浅尝Spring注解开发_简单理解BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor、ApplicationListener
Spring注解开发_Spring容器创建概述
浅尝Spring注解开发_Servlet3.0与SpringMVC

声明式事务

环境搭建

  1. 添加依赖:数据源、数据库驱动、Spring-jdbc模块

  2. 业务类

    UserDao

    @Repository
    public class UserDao {
    	
    	@Autowired
    	private JdbcTemplate jdbcTemplate;
    	public void insert(){
    		String sql = "INSERT INTO `tbl_user`(username,age) VALUES(?,?)";
    		String username = UUID.randomUUID().toString().substring(0, 5);
    		jdbcTemplate.update(sql, username,19);
    	}
    
    }
    

    UserService

    @Service
    public class UserService {
    	
    	@Autowired
    	private UserDao userDao;
    	
    	public void insertUser(){
    		userDao.insert();
    		//otherDao.other();xxx
    		System.out.println("插入完成...");
    		int i = 10/0;
    	}
    
    }
    
  3. 配置数据源、JdbcTemplate(Spring提供的简化数据库操作的工具)操作数据

    @Configuration
    public class TxConfig {
    	
    	//数据源
    	@Bean
    	public DataSource dataSource() throws Exception{
    		ComboPooledDataSource dataSource = new ComboPooledDataSource();
    		dataSource.setUser("root");
    		dataSource.setPassword("123456");
    		dataSource.setDriverClass("com.mysql.jdbc.Driver");
    		dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
    		return dataSource;
    	}
    	//jdbcTemplate
    	@Bean
    	public JdbcTemplate jdbcTemplate() throws Exception{
    		//Spring对@Configuration类会特殊处理;给容器中加组件的方法,多次调用都只是从容器中找组件
    		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource());
    		return jdbcTemplate;
    	}
    
    }
    

开启注解

  1. 给方法上标注 @Transactional 表示当前方法是一个事务方法

    UserService

    @Service
    public class UserService {
    	
    	@Autowired
    	private UserDao userDao;
    	
    	@Transactional
    	public void insertUser(){
    		userDao.insert();
    		//otherDao.other();xxx
    		System.out.println("插入完成...");
    		int i = 10/0;
    	}
    
    }
    
  2. @EnableTransactionManagement 开启基于注解的事务管理功能

    @EnableTransactionManagement
    @Configuration
    public class TxConfig {
        //...
    }
    
  3. 配置事务管理器来控制事务

    @EnableTransactionManagement
    @Configuration
    public class TxConfig {
    	
    	//数据源
    	@Bean
    	public DataSource dataSource() throws Exception{
    		ComboPooledDataSource dataSource = new ComboPooledDataSource();
    		dataSource.setUser("root");
    		dataSource.setPassword("123456");
    		dataSource.setDriverClass("com.mysql.jdbc.Driver");
    		dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
    		return dataSource;
    	}
    	
    	//jdbcTemplate
    	@Bean
    	public JdbcTemplate jdbcTemplate() throws Exception{
    		//Spring对@Configuration类会特殊处理;给容器中加组件的方法,多次调用都只是从容器中找组件
    		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource());
    		return jdbcTemplate;
    	}
    	
    	//注册事务管理器在容器中
    	@Bean
    	public PlatformTransactionManager transactionManager() throws Exception{
    		return new DataSourceTransactionManager(dataSource());
    	}
    
    }
    
  4. 测试

    • 出现异常时会回滚,不会插入数据库
    public class IOCTest_Tx {
    	
    	@Test
    	public void test01(){
    		AnnotationConfigApplicationContext applicationContext = 
    				new AnnotationConfigApplicationContext(TxConfig.class);
    	
    		UserService userService = applicationContext.getBean(UserService.class);
    		
    		userService.insertUser();
    		applicationContext.close();
    	}
    
    }
    

原理分析

与AOP相似,注册,包装,增强器,拦截器,执行目标方法
浅尝Spring注解开发_AOP原理及完整过程分析(源码)

  1. 进入@EnableTransactionManagement

    1. 利用TransactionManagementConfigurationSelector给容器中会导入组件,判断AdviceMode的值选择导入哪个组件

      1. 如果是PROXY导入两个组件(默认)

        • AutoProxyRegistrar(自动代理注册器)
        • ProxyTransactionManagementConfiguration(代理事务管理配置)
      2. 如果是ASPECTJ导入

        • TransactionManagementConfigUtils
  2. 分析AutoProxyRegistrar

    1. 用于给容器中注入Bean,调用registerBeanDefinitions()
    2. 调用AopConfigUtils.registerAutoProxyCreatorIfNecessary()最终注册InfrastructureAdvisorAutoProxyCreator(基础架构自动代理创建者)组件,也是后置处理器类型,利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用
    3. 这个类中同时注册了一个AnnotationAwareAspectJAutoProxyCreator(注解装配模式的AspectJ切面自动代理创建器),这个就是在AOP一开始注册的那个类,用于Bean实例化时的后置处理器
  3. 分析ProxyTransactionManagementConfiguration

    1. 给容器中注册事务增强器,如BeanFactoryTransactionAttributeSourceAdvisor(BeanFactory事务属性源增强器)

      1. 事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource解析事务注解

      2. 事务拦截器:

        1. TransactionInterceptor(它是一个 MethodInterceptor方法拦截器,和AOP中是相同的):保存了事务属性信息,事务管理器

        2. 在目标方法执行的时候执行拦截器链

        3. 事务拦截器

          1. 先获取事务相关的属性

          2. 再获取PlatformTransactionManager,如果事先没有添加指定任何transactionmanger

            最终会从容器中按照类型获取一个PlatformTransactionManager

          3. 执行目标方法invokeWithinTransaction(){ invocation.proceedWithInvocation() }

            • 如果异常,获取到事务管理器,利用事务管理回滚操作txInfo.getTransactionManager().rollback()
            • 如果正常,利用事务管理器,提交事务txInfo.getTransactionManager().commit()
posted @ 2022-05-04 17:55  蔚然丶丶  阅读(154)  评论(0编辑  收藏  举报