声明式事务使用
Spring事务是我们日常工作中经常使用的一项技术,Spring提供了编程、注解、aop切面三种方式供我们使用Spring事务,其中编程式事务因为对代码入侵较大所以不被推荐使用,注解和aop切面的方式可以基于需求自行选择,我们以注解的方式为例来分析Spring事务的原理和源码实现。
首先我们简单看一下Spring事务的使用方式,配置:
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
在需要开启事务的方法上加上@Transactional注解即可,这里需要注意的是,当tx:annotation-driven标签在不指定transaction-manager属性的时候,会默认寻找id固定名为transactionManager的bean作为事务管理器,如果没有id为transactionManager的bean并且在使用@Transactional注解时也没有指定value(事务管理器),程序就会报错。当我们在配置两个以上的tx:annotation-driven标签时,如下:</tx:annotation-driven></tx:annotation-driven>
< tx: annotation - driven transaction - manager = "transactionManager1" / >
<bean id = "transactionManager1"
class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" >
<property name = "dataSource" ref = "dataSource1" / >
</bean>
<tx: annotation - driven transaction - manager = "transactionManager2" / >
<bean id = "transactionManager2"
class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" >
<property name = "dataSource" ref = "dataSource2" / >
</bean>
这时第一个tx:annotation-driven会生效,也就是当我们使用@Transactional注解时不指定事务管理器,默认使用的事务管理器是transactionManager1,后文分析源码时会具体提到这些注意点。</tx:annotation-driven>
下面我们开始分析Spring的相关源码,首先看一下对tx:annotation-driven标签的解析,这里需要读者对Spring自定义标签解析的过程有一定的了解,笔者后续也会出相关的文章。锁定TxNamespaceHandler:</tx:annotation-driven>
TxNamespaceHandler
在spring-tx.jar包下找META-INF里的spring.handlers配置文件里,找到:
http://www.springframework.org/schema/tx=org.springframework.transaction.config.TxNamespaceHandler
其中org.springframework.transaction.config.TxNamespaceHandler就是spring事务的开端。
@Override
public void init() {
registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
}
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
/**
* Parses the {@code <tx:annotation-driven/>} tag. Will
* {@link AopNamespaceUtils#registerAutoProxyCreatorIfNecessary register an AutoProxyCreator}
* with the container as necessary.
*/
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
registerTransactionalEventListenerFactory(parserContext);
String mode = element.getAttribute("mode");
if ("aspectj".equals(mode)) {
// mode="aspectj"
registerTransactionAspect(element, parserContext);
}
else {
// mode="proxy"
AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
}
return null;
}
AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext)是十分重要的。
public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
Object eleSource = parserContext.extractSource(element);
// Create the TransactionAttributeSource definition.
RootBeanDefinition sourceDef = new RootBeanDefinition(
"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
sourceDef.setSource(eleSource);
sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
// Create the TransactionInterceptor definition.
RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
interceptorDef.setSource(eleSource);
interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registerTransactionManager(element, interceptorDef);
interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);
// Create the TransactionAttributeSourceAdvisor definition.
RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
advisorDef.setSource(eleSource);
advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
if (element.hasAttribute("order")) {
advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
}
parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
parserContext.registerComponent(compositeDef);
}
}
}
首先分析下 AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
可以看到在spring的声明周期内,InfrastructureAdvisorAutoProxyCreator将作为所有aop的实现者,事务只是其中一个增强。
注意上面的两行代码 currentPriority, requiredPriority。我们在上节中通过分析我们使用的aop增强器是AnnotationAwareAspectJAutoProxyCreator,但是整个spring生命周期内只能有一个aop的增强器。spring是通过增强器的优先级来决定留下哪一个,优先级就是那个在list中的index最大用哪个。
AopConfigUtils
可以看到 AnnotationAwareAspectJAutoProxyCreator 的优先级是高于 InfrastructureAdvisorAutoProxyCreator,所以对于引入了事务的spring,唯一留下的增强器就是AnnotationAwareAspectJAutoProxyCreator,回到 configureAutoProxyCreator方法继续分析。
if说明对于tx标签的解析只会做一次,就是说在配置文件里配两个事物管理器是没用的。
接下来就是注册了三个BeanDefinition。这三个bd也是spring事务的核心。简单解释下作用
AnnotationTransactionAttributeSource、
事务的属性,常见的就是传播行为,隔离级别,回滚配置。AnnotationTransactionAttributeSource是功能类,专门用来解析方法上的事务属。
TransactionInterceptor
它是一个advice,就是增强逻辑的具体实现
BeanFactoryTransactionAttributeSourceAdvisor
从名字看就知道了,这是一个advisor。在进行代理的时候,会被找出来并转为Interceptor执行。
这三个bean的关系是 BeanFactoryTransactionAttributeSourceAdvisor有两个成员变量就是AnnotationTransactionAttributeSource 和 TransactionInterceptor。
可以简单理解advisor就是advice + pointcut,BeanFactoryTransactionAttributeSourceAdvisor当然也是不例外的,只不过它还有个TransactionAttributeSource是用来解析被代理类的每个方法的事务属性,也就是说它的pointcut就是通过TransactionAttributeSource来辅助实现的。跟aop一样,对一个类增强就是要获取能对他切的advisor,那么对于事务其判断逻辑就是被代理类或者它的任意一个方法是否有@Transanctional注解。
没有回复内容