Spring笔记(5) - 声明式事务@EnableTransactionManagement注解源码分析
一.背景
前面详解了实现Spring事务的两种方式的不同实现:编程式事务和声明式事务,对于配置都使用到了xml配置,今天介绍Spring事务的注解开发,例如下面例子:
- 配置类:注册数据源、JDBC模板、事务管理器
//包扫描,将包下的dao、service注册到Spring容器中 @ComponentScan("com.hrh") //开启基于注解的事务管理,跟@Transactional注解配套使用 @EnableTransactionManagement //表明TxConfig是配置类 @Configuration public class TxConfig { //注册数据源 @Bean public DataSource dataSource() throws Exception { ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(); comboPooledDataSource.setUser("xxx"); comboPooledDataSource.setPassword("xxx"); comboPooledDataSource.setJdbcUrl("jdbc:mysql://xxx:3306/xxx"); comboPooledDataSource.setDriverClass("com.mysql.jdbc.Driver"); return comboPooledDataSource; } //注册jdbc模板 @Bean public JdbcTemplate jdbcTemplate() throws Exception { return new JdbcTemplate(dataSource()); } //注册事务管理器来控制事务 @Bean public PlatformTransactionManager manager() throws Exception { return new DataSourceTransactionManager(dataSource()); } }
- 业务代码:
@Repository public class UserDao { @Autowired private JdbcTemplate jdbcTemplate; public void insert(){ String sql ="insert into tab_person(name,age) values(?,?)"; String name = UUID.randomUUID().toString().substring(0, 5); jdbcTemplate.update(sql,name,19); } } @Service public class UserService{ @Autowired private UserDao userDao; //添加事务 @Transactional public void insert() { userDao.insert(); System.out.println("插入完成。"); int i = 10/0; } }
- 测试:从下面运行结果可以看出抛出了异常,在数据库中查看数据发现没有最新的数据插入,表明插入操作进行了回滚
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TxConfig.class); UserService bean = context.getBean(UserService.class); bean.insert(); context.close(); } 运行结果: 插入完成。 Exception in thread "main" java.lang.ArithmeticException: / by zero at com.hrh.service.UserService.insert(UserService.java:20)
二. @EnableTransactionManagement注解源码分析
1.流程
-
EnableTransactionManagement导入一个TransactionManagementConfigurationSelector组件
-
TransactionManagementConfigurationSelector默认导入两个组件:AutoProxyRegistrar和ProxyTransactionManagementConfiguration
-
AutoProxyRegistrar(利用后置处理器包装代理对象):注册一个InfrastructureAdvisorAutoProxyCreator组件(自动代理创建器),利用后置处理器机制在对象创建之后包装对象,返回一个代理对象(增强器),利用拦截器链执行方法
-
ProxyTransactionManagementConfiguration(注册配置):给容器注册各种组件,注册了事务增强器
-
4.1)事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource解析了注解上的各种属性信息
4.2)同时用到TransactionInterceptor事务拦截器:保存了事务属性信息、事务管理器
4.2.1)在目标方法执行时:执行拦截器链(即TransactionInterceptor)
4.2.2)TransactionInterceptor事务拦截器的作用:获取事务相关的属性,再获取事务管理器进行事务的执行、回滚或提交操作;
2.源码解析
- EnableTransactionManagement导入一个TransactionManagementConfigurationSelector组件
@Import({TransactionManagementConfigurationSelector.class}) public @interface EnableTransactionManagement { //默认为false boolean proxyTargetClass() default false; //默认为PROXY AdviceMode mode() default AdviceMode.PROXY; int order() default 2147483647; }
- TransactionManagementConfigurationSelector默认导入两个组件:AutoProxyRegistrar和ProxyTransactionManagementConfiguration
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> { //AdviceMode值在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[] { TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME}; default: return null; } } }
- AutoProxyRegistrar(利用后置处理器包装代理对象):注册一个InfrastructureAdvisorAutoProxyCreator组件(自动代理创建器),利用后置处理器机制在对象创建之后包装对象,返回一个代理对象(增强器),利用拦截器链执行方法
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; //注册一个InfrastructureAdvisorAutoProxyCreator组件(自动代理创建器) if (mode == AdviceMode.PROXY) { AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry); //proxyTargetClass在EnableTransactionManagement默认false if ((Boolean) proxyTargetClass) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); return; } } } } ..... } }
- AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry):自动代理创建器
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) { return registerAutoProxyCreatorIfNecessary(registry, null); } @Nullable public static BeanDefinition registerAutoProxyCreatorIfNecessary( BeanDefinitionRegistry registry, @Nullable Object source) { //给容器注册InfrastructureAdvisorAutoProxyCreator(是一个后置处理器),利用后置处理器机制在对象创建之后包装对象,返回一个代理对象(增强器),利用拦截器链执行方法 return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source); }
- AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry):自动代理创建器
- ProxyTransactionManagementConfiguration(注册配置):给容器注册各种组件,注册了事务增强器
@Configuration public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { //注册事务增强器BeanFactoryTransactionAttributeSourceAdvisor @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() { BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor(); //设置事务属性,从注解解析器获取注解上的事务属性值 advisor.setTransactionAttributeSource(transactionAttributeSource()); //设置了TransactionInterceptor事务拦截器 advisor.setAdvice(transactionInterceptor()); advisor.setOrder(this.enableTx.<Integer>getNumber("order")); return advisor; } //注册事务属性,解析注解中的各种属性,比如propagation、isolation、timeout等 @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionAttributeSource transactionAttributeSource() { //注解解析器 return new AnnotationTransactionAttributeSource(); } //注册了TransactionInterceptor事务拦截器:保存了事务属性信息、事务管理器 @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionInterceptor transactionInterceptor() { TransactionInterceptor interceptor = new TransactionInterceptor(); //保存了事务属性信息 interceptor.setTransactionAttributeSource(transactionAttributeSource()); if (this.txManager != null) { //保存了事务管理器 interceptor.setTransactionManager(this.txManager); } return interceptor; } }
- 注解解析器AnnotationTransactionAttributeSource
public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) { this.publicMethodsOnly = publicMethodsOnly; this.annotationParsers = new LinkedHashSet<TransactionAnnotationParser>(4); //添加spring事务注解的解析器 this.annotationParsers.add(new SpringTransactionAnnotationParser()); if (jta12Present) { //添加jta事务注解的解析器 this.annotationParsers.add(new JtaTransactionAnnotationParser()); } if (ejb3Present) { //添加Ejb3事务注解的解析器 this.annotationParsers.add(new Ejb3TransactionAnnotationParser()); } } public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) { AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes( element, Transactional.class); if (attributes != null) { //解析注解 return parseTransactionAnnotation(attributes); } else { return null; } } //解析注解Transactional上的每个属性 protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) { RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute(); Propagation propagation = attributes.getEnum("propagation"); rbta.setPropagationBehavior(propagation.value()); Isolation isolation = attributes.getEnum("isolation"); rbta.setIsolationLevel(isolation.value()); rbta.setTimeout(attributes.getNumber("timeout").intValue()); rbta.setReadOnly(attributes.getBoolean("readOnly")); rbta.setQualifier(attributes.getString("value")); List<RollbackRuleAttribute> rollbackRules = new ArrayList<RollbackRuleAttribute>(); for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) { rollbackRules.add(new RollbackRuleAttribute(rbRule)); } for (String rbRule : attributes.getStringArray("rollbackForClassName")) { rollbackRules.add(new RollbackRuleAttribute(rbRule)); } for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) { rollbackRules.add(new NoRollbackRuleAttribute(rbRule)); } for (String rbRule : attributes.getStringArray("noRollbackForClassName")) { rollbackRules.add(new NoRollbackRuleAttribute(rbRule)); } rbta.setRollbackRules(rollbackRules); return rbta; }
- 事务拦截器TransactionInterceptor:是一个MethodInterceptor,方法拦截器(4个通知方法整合成了增强器,增强器整合成了MethodInterceptor。我们在容器中放置了一个代理对象,当要执行代理对象时,方法拦截器就执行了)
public Object invoke(final MethodInvocation invocation) throws Throwable { // Work out the target class: may be {@code null}. // The TransactionAttributeSource should be passed the target class // as well as the method, which may be from an interface. Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); // Adapt to TransactionAspectSupport's invokeWithinTransaction... return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() { @Override public Object proceedWithInvocation() throws Throwable { return invocation.proceed(); } }); } protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation) throws Throwable { // If the transaction attribute is null, the method is non-transactional. //获取事务属性 final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass); //获取事务管理器 final PlatformTransactionManager tm = determineTransactionManager(txAttr); //获取执行的事务方法 final String joinpointIdentification = methodIdentification(method, targetClass, txAttr); if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { // Standard transaction demarcation with getTransaction and commit/rollback calls. //开启事务 TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal = null; try { // This is an around advice: Invoke the next interceptor in the chain. // This will normally result in a target object being invoked. //事务方法执行 retVal = invocation.proceedWithInvocation(); } catch (Throwable ex) { // target invocation exception //事务异常会获取事务管理器,利用事务管理器执行回滚操作 completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { cleanupTransactionInfo(txInfo); } //如果正常,利用事务管理器提交事务 commitTransactionAfterReturning(txInfo); return retVal; } else { final ThrowableHolder throwableHolder = new ThrowableHolder(); // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in. try { Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, new TransactionCallback<Object>() { @Override public Object doInTransaction(TransactionStatus status) { TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); try { return invocation.proceedWithInvocation(); } catch (Throwable ex) { if (txAttr.rollbackOn(ex)) { // A RuntimeException: will lead to a rollback. if (ex instanceof RuntimeException) { throw (RuntimeException) ex; } else { throw new ThrowableHolderException(ex); } } else { // A normal return value: will lead to a commit. throwableHolder.throwable = ex; return null; } } finally { cleanupTransactionInfo(txInfo); } } }); // Check result state: It might indicate a Throwable to rethrow. if (throwableHolder.throwable != null) { throw throwableHolder.throwable; } return result; } catch (ThrowableHolderException ex) { throw ex.getCause(); } catch (TransactionSystemException ex2) { if (throwableHolder.throwable != null) { logger.error("Application exception overridden by commit exception", throwableHolder.throwable); ex2.initApplicationException(throwableHolder.throwable); } throw ex2; } catch (Throwable ex2) { if (throwableHolder.throwable != null) { logger.error("Application exception overridden by commit exception", throwableHolder.throwable); } throw ex2; } } }
- 注解解析器AnnotationTransactionAttributeSource
- EnableTransactionManagement导入一个TransactionManagementConfigurationSelector组件
作者:huangrenhui
欢迎任何形式的转载,但请务必注明出处。
如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】。
如果,您希望更容易地发现我的新博客,不妨点击一下左下角的【关注我】。
如果,您对我的博客所讲述的内容有兴趣,请继续关注我的后续博客,我是【码猿手】。
如果,您希望更容易地发现我的新博客,不妨点击一下左下角的【关注我】。
如果,您对我的博客所讲述的内容有兴趣,请继续关注我的后续博客,我是【码猿手】。
限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。