spring 声明式事务源码分析

19 篇文章 1 订阅

第一步建源码分析调试环境,这里引用的是org.springframework4.3.12.RELEASE版本分析的,debug之前github上下载相关源码-地址

@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);
		
	}

}
@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
@ComponentScan("com.atguigu.tx")
@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/mysql");
		return dataSource;
	}
	
	//
	@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());
	}
	
}
@Test
	public void test01(){
		AnnotationConfigApplicationContext applicationContext = 
				new AnnotationConfigApplicationContext(TxConfig.class);
	
		UserService userService = applicationContext.getBean(UserService.class);
		
		userService.insertUser();
		applicationContext.close();
	}
1.EnableTransactionManagement源码分析

EnableTransactionManagement注解是开启事务的配置,进入该注解,发现同样,该注解引入了@Import注解(感觉像是套路一样),和开启自动代理的配置类似。

在这里插入图片描述

进入TransactionManagementConfigurationSelector类,查看其结构,发现其的父类实现了ImportSelector接口,这个接口前几篇的博客 说过,是给容器引入对象的,这个接口只有一个实现方法,方法的返回值为类名全路径的数组。

在这里插入图片描述

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

	/**
	 * {@inheritDoc}
	 * @return {@link ProxyTransactionManagementConfiguration} or
	 * {@code AspectJTransactionManagementConfiguration} for {@code PROXY} and
	 * {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()}, respectively
	 */
	@Override
	protected String[] selectImports(AdviceMode adviceMode) {
		switch (adviceMode) {
			case PROXY:
				return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
			case ASPECTJ:
				return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
			default:
				return null;
		}
	}

}

因为这个注解的AdviceMode默认为AdviceMode.PROXY,所以是默认返回AutoProxyRegistrar与ProxyTransactionManagementConfiguration这两个对象,下面来分析这两个对象

1.1 AutoProxyRegistrar

查看AutoProxyRegistrar发现,此类实现了ImportBeanDefinitionRegistrar 接口的,通过AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)实现相关自动代理创建器的创建
其实和前几篇提到的spring Aop源码中的套路类似


public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	private final Log logger = LogFactory.getLog(getClass());

	
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		boolean candidateFound = false;
		Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
		for (String annoType : annoTypes) {
			AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
			if (candidate == null) {
				continue;
			}
			Object mode = candidate.get("mode");
			Object proxyTargetClass = candidate.get("proxyTargetClass");
			if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
					Boolean.class == proxyTargetClass.getClass()) {
				candidateFound = true;
				if (mode == AdviceMode.PROXY) {
				   //关键点代码,注册自动代理创建器
					AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
					if ((Boolean) proxyTargetClass) {
						AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
						return;
					}
				}
			}
		}
		if (!candidateFound) {
			String name = getClass().getSimpleName();
			logger.warn(String.format("%s was imported but no annotations were found " +
					"having both 'mode' and 'proxyTargetClass' attributes of type " +
					"AdviceMode and boolean respectively. This means that auto proxy " +
					"creator registration and configuration may not have occurred as " +
					"intended, and components may not be proxied as expected. Check to " +
					"ensure that %s has been @Import'ed on the same class where these " +
					"annotations are declared; otherwise remove the import of %s " +
					"altogether.", name, name, name));
		}
	}

}

注册了InfrastructureAdvisorAutoProxyCreator.class 对象

在这里插入图片描述

点开发现和AspectJAwareAdvisorAutoProxyCreator方法类似,都是AbstractAdvisorAutoProxyCreator的子类,这个就不做赘述了,可以查看文章AnnotationAwareAspectJAutoProxyCreator 源码解析

在这里插入图片描述

1.2 ProxyTransactionManagementConfiguration

在这里插入图片描述

2.调试源码

开始debug项目,从这里可以看出返回的userService是一个代理对象,按F7(step into )

在这里插入图片描述
在这里插入图片描述

进入拦截器方法,进入拦截器执行方法

在这里插入图片描述
在这里插入图片描述

简单的分析就是这样,如果有时间和有兴趣,可以多了解下里面源码

在这里插入图片描述

总结:

原理:
1)、@EnableTransactionManagement
   利用TransactionManagementConfigurationSelector给容器中会导入组件
   导入两个组件
   AutoProxyRegistrar
   ProxyTransactionManagementConfiguration
2)、AutoProxyRegistrar:
   给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件;
   InfrastructureAdvisorAutoProxyCreator:?
   利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用;

3)、ProxyTransactionManagementConfiguration 做了什么?
   1、给容器中注册事务增强器;
      1)、事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource解析事务注解
      2)、事务拦截器:
      TransactionInterceptor;保存了事务属性信息,事务管理器;
      他是一个 MethodInterceptor;
      在目标方法执行的时候;
            执行拦截器链;
            事务拦截器:
              1)、先获取事务相关的属性
              2)、再获取PlatformTransactionManager,如果事先没有添加指定任何             transactionmanger最终会从容器中按照类型获取一个PlatformTransactionManager;
              3)、执行目标方法
              如果异常,获取到事务管理器,利用事务管理回滚操作;
              如果正常,利用事务管理器,提交事务

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值