Spring注解版-事务管理

一、事务管理注解使用步骤

  1. 使用@EnableTransactionManagement注解开启Spring事务管理,相当于xml配置中的<tx:annotation-driven/>;
  2. 向容器中注册PlatformTransactionManager事务管理器;
  3. 使用@Transactional注解标注目标方法, 使得Spring容器中的PlatformTransactionManager事务管理器能够管理目标方法的事务;
    还有些与数据连接的配置组件需要导入至容器中, 比如DataSource, JdbcTemplate…
// 配置类
@Configuration
// 开启事务管理 相当于xml配置中的<tx:annotation-driven/>
@EnableTransactionManagement
// 包扫描
@ComponentScan(basePackages = "study.bryan.spring.tx")
public class SpringTxConfig {
	// 注册DataSource
	@Bean
	public DataSource dataSource() throws Exception {
		// 这里使用的是Druid连接池, 所以需要到Druid的相关jar包
		Properties properties = new Properties();
		properties.put(DruidDataSourceFactory.PROP_URL, "xxx");
		properties.put(DruidDataSourceFactory.PROP_USERNAME, "xxx");
		properties.put(DruidDataSourceFactory.PROP_PASSWORD, "xxx");
		// 需要导入mysql驱动jar包
		properties.put(DruidDataSourceFactory.PROP_DRIVERCLASSNAME, "com.mysql.jdbc.Driver");
		return DruidDataSourceFactory.createDataSource(properties);
	}
	// 不整合mybatis下 注册JdbcTemplate 用于简化操作jdbc
	@Bean
	public JdbcTemplate jdbcTemplate(DataSource dataSource) {
		return new JdbcTemplate(dataSource);
	}
	// 向容器中注册一个TransactionManager, 事务管理器
	@Bean
	public PlatformTransactionManager transactionManager(DataSource dataSource) {
		return new DataSourceTransactionManager(dataSource);
	}
}

@Service("orderService")
public class OrderServiceImpl {
	@Autowired
	private OrderMapper orderMapper;
	// 开启目标方法的事务管理, 可以指定事务管理器transactionManager, 指定事务传播行为propagation, 指定事务的隔离级别isolation, 指定超时时间timeout, 指定为具体异常回滚rollbackFor, 等等
	@Transactional
	public Integer add() {
		Integer add = orderMapper.add();	
		int j = 1/0;		
		return add;
	}
}

二、@EnableTransactionManagement的作用

  1. 使用@Import注解向容器注册TransactionManagementConfigurationSelector
  2. TransactionManagementConfigurationSelector的父类实现ImportSelector接口并重写selectImports()方法,Spring会在容器启动时注册selectImports()方法中返回的类名的Bean信息, 源码中根据AdviceMode 代理模式返回不同的类名, 在@EnableTransactionManagementAdviceMode 的默认值是AdviceMode.PROXY(jdk), 所以TransactionManagementConfigurationSelector类默认向容器中注册了AutoProxyRegistrar,ProxyTransactionManagementConfiguration这两个类的Bean信息;
  3. 分析AutoProxyRegistrar类: 是一个实现ImportBeanDefinitionRegistrar接口的类, 并重写了registerBeanDefinitions()方法, 在此方法中可以利用BeanDefinitionRegistrySpring注册Bean信息, 这一部分其实就是SpringAOP的部分, 只不过最终向容器注册的Bean信息是ID"org.springframework.aop.config.internalAutoProxyCreator", 类为InfrastructureAdvisorAutoProxyCreatorBean, 而SpringAop注解启动默认注册是的AnnotationAwareAspectJAutoProxyCreator类, 这两个类的父类都是AbstractAutoProxyCreator,实现了BeanPostProcessor后置处理器和Aware接口,向容器注册InfrastructureAdvisorAutoProxyCreator这个类后, Spring就会在其他单例Bean实例化初始化之后调用AbstractAutoProxyCreator.postProcessAfterInitialization()方法为这些单例Bean包装创建代理对象; 这就是Spring事物管理底层其实是基于AOP原理的原因之一;debug运行至AbstractAutoProxyCreator.postProcessAfterInitialization()方法时可以看到,SpringAOP为目标Bean创建代理对象时,需要先获取所有适用目标方法的增强器(通知方法), 在事务管理中对目标方法所使用的增强器是BeanFactoryTransactionAttributeSourceAdvisor;
  4. 分析ProxyTransactionManagementConfiguration类: 此类是一个配置类, 通过@Bean注解向IOC容器注册了BeanFactoryTransactionAttributeSourceAdvisor(增强器),TransactionAttributeSource(事物属性源),TransactionInterceptor(事物拦截器);BeanFactoryTransactionAttributeSourceAdvisor就是事物管理的增强器, 只有将其注入值IOC容器中, Spring在为其他Bean实例化初始化后, 才会为Bean创建代理对象;其中TransactionAttributeSource中带有TransactionAnnotationParser事物注解解析器, 就是用来解析目标方法上@Transactional注解中各个属性值, 将这些属性值记录至TransactionAttribute中;TransactionInterceptor是一个MethodInterceptor, 在目标方法执行时SpringAOP会通过MethodInterceptor拦截器链拦截目标方法, 调用invoke()方法来执行各种通知方法;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
// 使用@Import向容器中注册TransactionManagementConfigurationSelector
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
	...其他源码
	AdviceMode mode() default AdviceMode.PROXY;	
	...其他源码
}
// TransactionManagementConfigurationSelector的父类实现了ImportSelector接口, 并重写selectImports()方法,Spring会在容器启动时注册selectImports()方法中返回的类名的Bean信息, 在@EnableTransactionManagement 中AdviceMode 的默认值是AdviceMode.PROXY, 所以selectImports()默认返回了AutoProxyRegistrar,ProxyTransactionManagementConfiguration这两个类
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
	@Override
	protected String[] selectImports(AdviceMode adviceMode) {
		switch (adviceMode) {
			case PROXY:
				return new String[] {AutoProxyRegistrar.class.getName(),
						ProxyTransactionManagementConfiguration.class.getName()};
			case ASPECTJ:
				return new String[] {determineTransactionAspectClass()};
			default:
				return null;
		}
	}
	private String determineTransactionAspectClass() {
		return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
				TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
				TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
	}
}
// AutoProxyRegistrar 是一个实现ImportBeanDefinitionRegistrar 接口的类, 并重写了registerBeanDefinitions()方法, 在此方法中可以利用BeanDefinitionRegistry 向Spring注册Bean信息, 这一部分其实就是SpringAOP的部分, 只不过最终向容器注册的Bean信息是ID为"org.springframework.aop.config.internalAutoProxyCreator", 类为InfrastructureAdvisorAutoProxyCreator的Bean, 而SpringAop注解启动默认注册是的AnnotationAwareAspectJAutoProxyCreator类, 这两个类的父类都是AbstractAutoProxyCreator,实现了Bean后置处理器和Aware接口, 这就是Spring事物管理底层其实是基于AOP原理的原因;
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		boolean candidateFound = false;
		Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
		for (String annType : annTypes) {
			AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
			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) {
					// 在这里注册了InfrastructureAdvisorAutoProxyCreator
					AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
					if ((Boolean) proxyTargetClass) {
						AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
						return;
					}
				}
			}
		}
		... 其他源码
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值