浅尝Spring注解开发_声明式事务及原理
浅尝Spring注解开发_声明式事务及原理
浅尝Spring注解开发,基于Spring 4.3.12
包含声明式事务使用、基本原理分析
浅尝Spring注解开发_自定义注册组件、属性赋值、自动装配
浅尝Spring注解开发_Bean生命周期及执行过程
浅尝Spring注解开发_AOP原理及完整过程分析(源码)
浅尝Spring注解开发_声明式事务及原理
浅尝Spring注解开发_简单理解BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor、ApplicationListener
Spring注解开发_Spring容器创建概述
浅尝Spring注解开发_Servlet3.0与SpringMVC
声明式事务
环境搭建
-
添加依赖:数据源、数据库驱动、Spring-jdbc模块
-
业务类
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; } }
-
配置数据源、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; } }
开启注解
-
给方法上标注 @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; } }
-
@EnableTransactionManagement 开启基于注解的事务管理功能
@EnableTransactionManagement @Configuration public class TxConfig { //... }
-
配置事务管理器来控制事务
@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()); } }
-
测试
- 出现异常时会回滚,不会插入数据库
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原理及完整过程分析(源码)
-
进入
@EnableTransactionManagement
-
利用
TransactionManagementConfigurationSelector
给容器中会导入组件,判断AdviceMode
的值选择导入哪个组件-
如果是
PROXY
导入两个组件(默认)AutoProxyRegistrar(自动代理注册器)
ProxyTransactionManagementConfiguration(代理事务管理配置)
-
如果是
ASPECTJ
导入TransactionManagementConfigUtils
-
-
-
分析
AutoProxyRegistrar
- 用于给容器中注入Bean,调用
registerBeanDefinitions()
- 调用
AopConfigUtils.registerAutoProxyCreatorIfNecessary()
最终注册InfrastructureAdvisorAutoProxyCreator(基础架构自动代理创建者)
组件,也是后置处理器类型,利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用 - 这个类中同时注册了一个
AnnotationAwareAspectJAutoProxyCreator(注解装配模式的AspectJ切面自动代理创建器)
,这个就是在AOP一开始注册的那个类,用于Bean实例化时的后置处理器
- 用于给容器中注入Bean,调用
-
分析
ProxyTransactionManagementConfiguration
-
给容器中注册事务增强器,如
BeanFactoryTransactionAttributeSourceAdvisor(BeanFactory事务属性源增强器)
-
事务增强器要用事务注解的信息,
AnnotationTransactionAttributeSource
解析事务注解 -
事务拦截器:
-
TransactionInterceptor
(它是一个MethodInterceptor
方法拦截器,和AOP中是相同的):保存了事务属性信息,事务管理器 -
在目标方法执行的时候执行拦截器链
-
事务拦截器
-
先获取事务相关的属性
-
再获取
PlatformTransactionManager
,如果事先没有添加指定任何transactionmanger
最终会从容器中按照类型获取一个
PlatformTransactionManager
-
执行目标方法
invokeWithinTransaction(){ invocation.proceedWithInvocation() }
- 如果异常,获取到事务管理器,利用事务管理回滚操作
txInfo.getTransactionManager().rollback()
- 如果正常,利用事务管理器,提交事务
txInfo.getTransactionManager().commit()
- 如果异常,获取到事务管理器,利用事务管理回滚操作
-
-
-
-