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 导致事物不生效
2.重点:private 事物不生效原因 通过位与计算,判断是否为 Public,对应的几类修饰符如下: PUBLIC: 1 PRIVATE: 2 PROTECTED: 4
异常不匹配原因
1.回滚入口
2.重点,事物是否生效判断
3.进入 rollbackOn() 方法,判断该异常是否能进行回滚,这个需要判断主方法抛出的 Exception() 异常,是否在 @Transactional 的配置中
4.getDepth() 看一下异常规则匹配逻辑
5.默认捕获异常
