目录
1、@EnableTransactionManagement
2、TransactionManagementConfigurationSelector
4、InfrastructureAdvisorAutoProxyCreator
5、ProxyTransactionManagementConfiguration
5.1 BeanFactoryTransactionAttributeSourceAdvisor
5.2 TransactionAttributeSource
在配置类中加上@EnableTransactionManagement注解即可开启。
注解使用了@Import功能向容器导入组件

这个类是一个ImportSelector类型实现类,利用ImportSelector功能,默认向容器导入2个组件,分别是【AutoProxyRegistrar】、【ProxyTransactionManagementConfiguration】

AutoProxyRegistrar是ImportBeanDefinitionRegistrar实现类,容器在注册组件时调用registerBeanDefinitions方法。AutoProxyRegistrar利用registerBeanDefinitions方法向容器导入InfrastructureAdvisorAutoProxyCreator组件


打开InfrastructureAdvisorAutoProxyCreator源码可发现该类是一个SmartInstantiationAwareBeanPostProcessor类型的实现类。
在容器创建对象完成初始化后通过调用postProcessAfterInitialization()方法判断该对象是否含有符合条件的Advisor增强器,若是符合,则将对象包装成代理对象返回给IOC容器

进入wrapIfNecessary方法中,getAdvicesAndAdvisorsForBean方法是返回适用于对象的增强器

通过createProxy方法创建代理对象并返回,该代理对象包含了对象的增强器、目标对象等信息。

这是一个配置类,主要是向容器注册 BeanFactoryTransactionAttributeSourceAdvisor事务增强器、AnnotationTransactionAttributeSource事务注解属性、 TransactionInterceptor事务拦截器
可在容器中注册TransactionManagementConfigurer类型对象,指定默认事务管理器,通过ProxyTransactionManagementConfiguration的父类AbstractTransactionManagementConfiguration的setConfigurers方法完成注入。
(一般都是通过@Bean直接往容器注册事务管理器,若是注册多个事务管理器,可通过@Transactional的value属性指定事务管理器)

这是一个Spring事务增强器Advisor,用于容器创建对象完成初始化后,判断对象是否需要事务增强,从而将对象包装成代理对象。
增强器配置TransactionInterceptor事务拦截器、TransactionAttributeSource事务注解属性
这是一个解析@Transactional注解属性的解析器



这是一个事务拦截器,后续代理对象调用具体方法,会生成对应的拦截器链,通过拦截器链实现事务操作。

拦截器链调用invoke方法的invokeWithinTransaction方法中实现事务操作


代理对象调用方法具体运行步骤参考SpringAOP-底层原理解析_Just-Today的博客-CSDN博客,原理大致一致
- package com.mzp.component.tx;
-
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.jdbc.core.JdbcTemplate;
- import org.springframework.stereotype.Repository;
-
- import java.util.UUID;
-
- @Repository
- public class TestDao {
- @Autowired
- private JdbcTemplate jdbcTemplate;
-
- public void insert(){
- String id = UUID.randomUUID().toString();
- String sql = "insert into person values(?,?,?)";
- jdbcTemplate.update(sql,id, "jaclk", 1);
- }
- }
- package com.mzp.component.tx;
-
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
-
- @Service
- public class TestService {
- @Autowired
- private TestDao testDao;
-
- @Transactional
- public void insert(){
- testDao.insert();
- int i = 1/0;
- }
- }
- package com.mzp.component.config;
-
- import com.alibaba.druid.pool.DruidDataSource;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.ComponentScan;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.context.annotation.PropertySource;
- import org.springframework.jdbc.core.JdbcTemplate;
- import org.springframework.jdbc.datasource.DataSourceTransactionManager;
- import org.springframework.transaction.PlatformTransactionManager;
- import org.springframework.transaction.annotation.EnableTransactionManagement;
-
- import javax.sql.DataSource;
-
- @Configuration
- @EnableTransactionManagement
- @ComponentScan("com.mzp.component.tx")
- @PropertySource("datasource.properties")
- public class TxConfig {
- @Value("${jdbc.username}")
- private String username;
- @Value("${jdbc.password}")
- private String pass;
- @Value("${jdbc.driver}")
- private String driver;
- @Value("${jdbc.url}")
- private String url;
-
- @Bean
- public DataSource dataSource(){
- DruidDataSource druidDataSource = new DruidDataSource();
- druidDataSource.setUsername(username);
- druidDataSource.setPassword(pass);
- druidDataSource.setUrl(url);
- druidDataSource.setDriverClassName(driver);
- return druidDataSource;
- }
-
- @Bean
- public JdbcTemplate jdbcTemplate(){
- return new JdbcTemplate(dataSource());
- }
-
- @Bean
- public PlatformTransactionManager transactionManager(){
- return new DataSourceTransactionManager(dataSource());
- }
- }
- @Test
- public void test12(){
- ApplicationContext applicationContext = new AnnotationConfigApplicationContext(TxConfig.class);
- TestService testService = applicationContext.getBean(TestService.class);
- testService.insert();
- }