Spring @Transactional 原理解析

项目准备

创建 dao 层

@Repository
public class AccountDao {

	@Autowired
	private JdbcTemplate jdbcTemplate;

	public void save() {
		jdbcTemplate.execute("INSERT INTO `mp`.`user`(`id`, `name`, `age`, `email`, `manager_id`, `create_time`, `update_time`, `version`, `deleted`) VALUES (777777, 'doudou', 40, 'boss@baomidou.com', NULL, 20190111142020, NULL, 1, 0);");
	}
}

创建 service 层

@Service
public class AccountService {

	@Autowired
	private AccountDao accountDao;

	@Transactional
	public void save() {
		accountDao.save();
		String str = null;
		str.length();
	}
}

创建事物配置文件

@Configuration
@ComponentScan("com.user.service")
@EnableTransactionManagement        // 开启事物管理
public class TxConfig {

	/**
	 * 数据源
	 */
	@Bean
	public DataSource dataSource() {
		DriverManagerDataSource dataSource = new DriverManagerDataSource();
		dataSource.setUsername("root");
		dataSource.setPassword("123456");
		dataSource.setDriverClassName("com.mysql.jdbc.Driver");
		//dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
		dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/mp");
		return dataSource;
	}

	/**
	 * jdbc template
	 */
	@Bean
	public JdbcTemplate jdbcTemplate(DataSource dataSource) {
		return new JdbcTemplate(dataSource);
	}

	/**
	 * 平台事物管理
	 */
	@Bean
	public PlatformTransactionManager transactionManager(DataSource dataSource) {
		return new DataSourceTransactionManager(dataSource);
	}
}

启动类

public class TxMain {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TxConfig.class);
		AccountService accountService = (AccountService) applicationContext.getBean("accountService");
		accountService.save();
		applicationContext.close();
	}
}

事物不生效场景

具体场景参考第一张图


源码解读

开启事物

  • 通过 @EnableTransactionManagement 注解开启事物,该注解会 @Import TransactionManagementConfigurationSelector,Selector 是一个 ImportSelector,selectImports() 方法 返回 AutoProxyRegistrar、ProxyTransactionManagementConfiguration,这样就相当于开启代理功能事物管理功能
  • ProxyTransactionManagementConfiguration 是一个被 @Configuration 标注的配置类,会将下面三个对象注册到 bean 容器中
    • TransactionAttributeSource:事物的属性源,用来获取事物的相关配置
    • TransactionInterceptor:事物的拦截器,获取事物、执行业务、判断是否抛异常、提交或回滚事物
    • BeanFactoryTransactionAttributeSourceAdvisor:事物属性源通知者,用于给 aop 提供事物属性源和拦截器

@Transaction 执行原理

1.代码入口

2.spring 事物由 aop 实现,所以方法调用会走代理

3.调用父类 proceed() 方法

4.aop 代理对象调用,调用 TransactionInterceptor 的 invoke()

5.调用事物拦截器,调用 TransactionAspectSupport 的 invokeWithinTransaction 处理事物

6.事物处理核心逻辑
判断事务是否开启、创建事物、目标方法执行、事务回滚、事务提交


private 导致事物不生效

1.getTransactionAttribute(),关注获取事务配置的方法 computeTransactionAttribute()

2.重点:private 事物不生效原因

通过位与计算,判断是否为 Public,对应的几类修饰符如下:
PUBLIC: 1
PRIVATE: 2
PROTECTED: 4


异常不匹配原因

1.回滚入口

2.重点,事物是否生效判断

3.进入 rollbackOn() 方法,判断该异常是否能进行回滚,这个需要判断主方法抛出的 Exception() 异常,是否在 @Transactional 的配置中

4.getDepth() 看一下异常规则匹配逻辑

5.默认捕获异常

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tytler

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值