本文参考:《Spring源码深度解析》及源码走读.培养源码阅读思想
文章目录
- 1.必须懂的几个类
- 2.1 提取器驱动(装载)的advisor:BeanFactoryTransactionAttributeSourceAdvisor
- 2.2 @Transation注解元数据提取器:TransactionAttributeSource
- 2.3 事务执行器\拦截器:TransactionInterceptor
- 2. 事务管理入口
- 3. 构造器:事务拦截器基本配置查找与生成代理
- 4. 事务拦截器
先放图,du害一下大家,
1.必须懂的几个类
试想一下,如果Connection支持事务提交回滚(底层支持),那么你如何来设计你的事务处理框架?
我相信很多人的想法都是
- 先读取 @Transation注解的属性.生成一个对象(存放事务相关)
- 根据得到的该对象进行事务的commit,失败回滚,最终事务清除.
Spring框架对事务的支持大概也是这样的步骤,Spring支持嵌入事务,即方法中嵌套方法,如果都支持事务,则在里面的事务结束或者失败之后,外面的事务继续执行.
我们刚才提到 @Transation注解的属性提取,那么必定需要这样一个类去做提取的操作,提取的对象存储也需要一个相应类,用什么方式执行事务,这些都是我们后面需要讨论的内容,但是,在此之前,我们先看几个类,我们已经知道了实现事务的大概步骤,那么我们需要来看一下,Spring怎么去实现这些步骤的.
2.1 提取器驱动(装载)的advisor:BeanFactoryTransactionAttributeSourceAdvisor
我们知道Spring框架大量的使用了接口,可以想象,对于 @Transation注解的提取,Spring必定也是通过接口的实现类来定义提取方法(下一个会讲到),所以我们可以想象,我们需要一个类来承接这些接口和其他的属性.我们这里要讲的就是这个类。
我们看一下类上的注解:
- Advisor driven by a TransactionAttributeSource, used to include a transaction advice bean for methods that are transactional.
包含一个 TransactionAttributeSource,用于事务通知。我们暂且不管 TransactionAttributeSource类的作用,目前我们可以知道的就是BeanFactoryTransactionAttributeSourceAdvisor他会装载和提供一个 TransactionAttributeSource类。
我们看他是怎么实现 TransactionAttributeSource的。
@SuppressWarnings("serial")
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
//这个就是我们念念不忘的TransactionAttributeSource
private TransactionAttributeSource transactionAttributeSource;
//因为BeanFactoryTransactionAttributeSourceAdvisor 继承了PointCut接口,所以需要实现getPointCut方法
//而获取到的PointCut类会返回我们需要的TransactionAttributeSource。
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
}
很容易我们看到了TransactionAttributeSource 这个类,并且因为BeanFactoryTransactionAttributeSourceAdvisor继承了Pointcut接口,需要实现getPointcut方法,相当于是
通过得到PointCut实现类,再获取TransactionAttributeSource
2.2 @Transation注解元数据提取器:TransactionAttributeSource
@Transation的提取需要一定的规则,而不同的方式可能对应不同的规则,所以Spring利用接口的方式,制定提取的抽象。通过继承实现不同的提取规则。
首先你要知道 TransactionAttributeSource是一个接口,我们看一下类的描述
- Strategy interface used by TransactionInterceptor for metadata retrieval.
Implementations know how to source transaction attributes, whether from configuration, metadata attributes at source level (such as Java 5 annotations), or anywhere else.
提供给TransactionInterceptor拦截器用于事务元数据提取的接口.
但是接口需要实现类,因为是注解解析,这边的具体实现类是 AnnotationTransactionAttributeSource
作为一个注解提取器, AnnotationTransactionAttributeSource如何实现提取呢?
3.1 真实注解处理器:TransactionAnnotationParser
这边就给你答案,那就是TransactionAnnotationParser,看到该类的构造方法.必定会注入SpringTransactionAnnotationParser,这个类,这也是我们后面处理注解需要注意的。
public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
this.publicMethodsOnly = publicMethodsOnly;
this.annotationParsers = new LinkedHashSet<TransactionAnnotationParser>(2);
this.annotationParsers.add(new SpringTransactionAnnotationParser());
if (jta12Present) {
this.annotationParsers.add(new JtaTransactionAnnotationParser());
}
if (ejb3Present) {
this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
}
}
2.3 事务执行器\拦截器:TransactionInterceptor
首先知道一点就是 ****实现了 MethodInterceptor接口,需要实现这个类的 invoke方法,事务处理的具体逻辑就在这里,而 MethodInterceptor又会在代理创建的时候被调用,所以我们基本知道该拦截器实现事务管理是通过invoke方法在代理的时候实现。
我们在后面的描述中会讲到具体实现,别着急
关注一下类上的注释:
- AOP Alliance MethodInterceptor for declarative transaction management using the common Spring transaction infrastructure (PlatformTransactionManager)
- TransactionInterceptors are thread-safe.
事务管理和线程安全
2. 事务管理入口
2.1 注解式
还记得开启事务的注解式什么吗?我错,我知道你不记得了。
开启事务的注解是 EnableTransactionManagement,我们可以查看一下这个注解的使用,
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
boolean proxyTargetClass() default false;
//实现事务的方式(proxy或者aspectj)
AdviceMode mode() default AdviceMode.PROXY;
int order() default Ordered.LOWEST_PRECEDENCE;
}
很好,我们看到这个注解有一个mode,能够配置事务管理实现的方式,默认是PROXY.
在注解上面有一个 @Import注解,如果你告诉我不懂,我就是一巴掌过去. @Import注解引入一个Selector类,我们要看一下他是做什么幺蛾子的。
3.1 事务管理选择器:TransactionManagementConfigurationSelector
这个注解继承了AdviceModeImportSelector,实现selectImport方法,朔本回源,在Mvc启动的时候会调用Selector,也就是这样启动的.这边我们不细究,知道一个大概:
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[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
default:
return null;
}
}
}
这里看到了AdviceMode 的选择,我们只分析PROXY的方式,不要问为什么,问就是我菜.
PROXY的方式会返回两个类:AutoProxyRegistrar和ProxyTransactionManagementConfiguration
幺蛾子就出在这里面.
4.1 注册代理构造器:AutoProxyRegistrar
这个类只有一个方法,这个方法会去注册一些BeanDefinition.
@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);
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;
}
}
}
}
}
虽然这个类叽里呱啦的说了一堆,但是重要的是这一行代码,这个方法会为我们注册一个很重要的类:InfrastructureAdvisorAutoProxyCreator,自动代理构造器,我们对于advisor的查找和代理的实现都在这个类中实现,后面我们会说道。
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
4.2 事务注解驱动配置:ProxyTransactionManagementConfiguration
这个类,会为我们注册几个Bean,就是我们一开头说的,事务注解元数据提取器、事务处理拦截器、提取器承载类
@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
//事务注解提取器的承载类
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
//注入事务注解提取器
advisor.setTransactionAttributeSource(transactionAttributeSource());
//注入拦截器
advisor.setAdvice(transactionInterceptor());
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
return advisor;
}
//事务注解提取器
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
//事务注解提取器的具体实现
return new AnnotationTransactionAttributeSource();
}
//拦截器
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor() {
TransactionInterceptor interceptor = new TransactionInterceptor();
//注入事务注解提取器
interceptor.setTransactionAttributeSource(transactionAttributeSource());
if (this.txManager != null) {
//事务管理器:PlatformTransactionManager
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
2.2 XML式
3.1 事务命名空间处理器:TxNamespaceHandler
这个类实现了NameSpaceHandler,Spring框架会实现NamespaceHandler接口实现类的调用,这个我们暂时不管他。
可以想象到,和注解处理的方式应该类似,这边也应该注入,我们刚才讲的三个类.所以我们来看一下代码实现
@Override
public void init() {
registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
}
这边注册了三个BeanDefinitionParser的类,用屁股想象都知道,他大概想要去做什么事情,但是我们还是一个一个来看一下.
4.1 TxAdviceBeanDefinitionParser:注册事务注解提取器(或直接读取事务配置)
看到这边会去提取xml的元素,然后判断是否手动在XML中写入了事务相关属性,parseAttributeSource这个方法会去解析相关的属性(只读、超时时间…)
如果不是xml方式去注入的话,就需要去注册一个AnnotationTransactionAttributeSource,让这个类去提取**@Transational**上的属性,然后生成对应类.
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
builder.addPropertyReference("transactionManager", TxNamespaceHandler.getTransactionManagerName(element));
List<Element> txAttributes = DomUtils.getChildElementsByTagName(element, ATTRIBUTES_ELEMENT);
if (txAttributes.size() > 1) {
parserContext.getReaderContext().error(
"Element <attributes> is allowed at most once inside element <advice>", element);
}
else if (txAttributes.size() == 1) {
// Using attributes source.
Element attributeSourceElement = txAttributes.get(0);
RootBeanDefinition attributeSourceDefinition = parseAttributeSource(attributeSourceElement, parserContext);
builder.addPropertyValue("transactionAttributeSource", attributeSourceDefinition);
}
else {
// Assume annotations source.
builder.addPropertyValue("transactionAttributeSource",
new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"));
}
}
4.2 注册事务基础Bean配置
等下我们看代码的时候你会发现,他实现了和事务注解驱动配置:ProxyTransactionManagementConfiguration类似的功能:
@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;
}
这边我们依然只看PROXY的方式,我们可以看到下面的代码基本可以分成四步:
- AopNamespaceUtils.registerAutoProxyCreatorIfNecessary:注册InfrastructureAdvisorAutoProxyCreator以及xml配置的解析,不具体看了
- 注入AnnotationTransactionAttributeSource
- 注入TransactionInterceptor
- 注入BeanFactoryTransactionAttributeSourceAdvisor
- 注册上述的组件到context
public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
//注册InfrastructureAdvisorAutoProxyCreator类和解析XML属性
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
Object eleSource = parserContext.extractSource(element);
//注入AnnotationTransactionAttributeSource
RootBeanDefinition sourceDef = new RootBeanDefinition(
"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
sourceDef.setSource(eleSource);
sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
//注入TransactionInterceptor
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);
//注入BeanFactoryTransactionAttributeSourceAdvisor
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);
//注册到context
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);
}
}
}
4.3 注册事务管理器
这个类应该是解析xml上面的注解来注册事务管理器的,我们看一下这边的注释
- Parser for the tx:jta-transaction-manager/ XML configuration element, autodetecting WebLogic and WebSphere servers and exposing the corresponding JtaTransactionManager subclass.
代码里面会根据不同的方式去注册事务管理器.
static String resolveJtaTransactionManagerClassName() {
if (weblogicPresent) {
return WEBLOGIC_JTA_TRANSACTION_MANAGER_CLASS_NAME;
}
else if (webspherePresent) {
return WEBSPHERE_TRANSACTION_MANAGER_CLASS_NAME;
}
else {
return JTA_TRANSACTION_MANAGER_CLASS_NAME;
}
}
3. 构造器:事务拦截器基本配置查找与生成代理
废话不多说,我们来看一下InfrastructureAdvisorAutoProxyCreator这个类,这个类隔代实现了BeanPostProcessor接口,对于BeanPostProcessor,我们看一下类的注释
- Factory hook that allows for custom modification of new bean instances, e.g. checking for marker interfaces or wrapping them with proxies.
大概就是为Bean工厂创建的Bean实例提供一个钩子,在Bean调用之前做一些修饰操作.
实现postProcessAfterInitialization才能实现上面所说的操作,我们看一下这个方法:
注意类上的注释:通过配置监听器实现代理,这边设置缓存用过特定key查找,没有找到会进入wrapIfNecessary方法,根据注释,我们可以知道,这个方法大概就是要去生成一个代理了。
/**
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
* @see #getAdvicesAndAdvisorsForBean
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
通过一些列的查找,如果找到对应的代理类就直接返回,否则
- 先去查找拦截器
- 在通过拦截器实现代理
/**
* Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
* @param bean the raw bean instance
* @param beanName the name of the bean
* @param cacheKey the cache key for metadata access
* @return a proxy wrapping the bean, or the raw bean instance as-is
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 查找拦截器
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//生成代理
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
我们下面通过这两部分来分析一下
2.1 拦截器查找
这里进入拦截器的查找,如果查找到的拦截器为空, 返回空数组,否则返回拦截器数组
@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
查找过程又分成两步
- 查找所有拦截器
- 根据找到的所有拦截器,查找合适的拦截器
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
3.1 查找所有拦截器
这边的这个方法处理是这样的
- 从BeanFactory(或者缓存数组)中拿到advisor的字符串名称
- 进行一些判断,然后从BeanFactory里面获取Advisor实例
- 组装List返回
虽然我不知道BeanFactory怎么去拿到这些advisor,能力有限,以后再看,但是我们刚才开篇注册的三个Advisor这边应该是可以拿到的。
public List<Advisor> findAdvisorBeans() {
String[] advisorNames = null;
synchronized (this) {
advisorNames = this.cachedAdvisorBeanNames;
//从BeanFactory(或者缓存数组)中拿到advisor的字符串名称
if (advisorNames == null) {
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
}
if (advisorNames.length == 0) {
return new LinkedList<Advisor>();
}
List<Advisor> advisors = new LinkedList<Advisor>();
for (String name : advisorNames) {
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
//......................省略
//进行一些判断,然后从BeanFactory里面获取Advisor实例
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
}
}
}
return advisors;
}
3.2 根据找到的所有拦截器,查找合适的拦截器
这一步的操作关键的代码在这边,我们舍去一些操作,直接来看是怎么查找ApplyAdvisor的
AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
这边有一种Advisor叫做IntroductionAdvisor ,这个接口网上说好像是类级别上的增强,具体可以查阅对应资料,但是我们这边不关注这个类.
我们这边需要关注的是canApply这个方法,因为他是判断Advisor是否适用于当前事务管理的依据.
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
往下看,这边可以看到,第二个if判断判断了类是否是PointcutAdvisor,刚才上面介绍的BeanFactoryTransactionAttributeSourceAdvisor类就是实现了PointcutAdvisor接口,所以这边他要起到作用了.
这边传入getPointcut方法返回的对象,在上面的介绍中说到,内部实现了TransactionAttributeSourcePointcut
即当前的getPointcut方法传入TransactionAttributeSourcePointcut
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
canApply方法需要关注两个地方
- MethodMatcher的获取
- 调用matches方法
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
//MethodMatcher的获取
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
//循环通过MethodMatcher的matches方法匹配
Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
4.1 获取方法匹配器:MethodMatcher
上面说的,传入的pointcut是TransactionAttributeSourcePointcut类,所以直接查看这个类是怎么获取MethodMatcher的:
@Override
public final MethodMatcher getMethodMatcher() {
return this;
}
这边看到实现的getMethodMatcher方法直接返回this,也就是说,返回的Match就是TransactionAttributeSourcePointcut…
4.2 方法匹配器匹配,返回结果
既然我们已经知道了MethodMatcher,就要去看一下matchs到底是怎么匹配的.
@Override
public boolean matches(Method method, Class<?> targetClass) {
if (TransactionalProxy.class.isAssignableFrom(targetClass)) {
return false;
}
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
从刚才的分析可以看到,这边拿到的TransactionAttributeSourcePointcut是BeanFactoryTransactionAttributeSourceAdvisor类中的内部类,并实现了getTransactionAttributeSource方法.
可以参考上面介绍BeanFactoryTransactionAttributeSourceAdvisor,这里的TransactionAttributeSource注入的是AnnotationTransactionAttributeSource
所以我们来看一下这边的实现,依然是先通过缓存去获取,如果没有获取到才去解析。那么如何解析呢.
@Override
public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
Object cacheKey = getCacheKey(method, targetClass);
Object cached = this.attributeCache.get(cacheKey);
if (cached != null) {
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
return null;
}
else {
return (TransactionAttribute) cached;
}
}
else {
TransactionAttribute txAtt = computeTransactionAttribute(method, targetClass);
// Put it in the cache.
if (txAtt == null) {
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
}
else {
if (logger.isDebugEnabled()) {
Class<?> classToLog = (targetClass != null ? targetClass : method.getDeclaringClass());
logger.debug("Adding transactional method '" + classToLog.getSimpleName() + "." +
method.getName() + "' with attribute: " + txAtt);
}
this.attributeCache.put(cacheKey, txAtt);
}
return txAtt;
}
}
5.1 解析@Transation注解
这边的解析分成四种情况,任意一种满足则退出,方法上的注释也说明了这些:
- 解析当前方法上的注解
- 解析当前类上的注解
- 解析类实现的接口的方法上的注解
- 解析类实现的接口上的注解
protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
// Don't allow no-public methods as required.
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
// Ignore CGLIB subclasses - introspect the actual user class.
Class<?> userClass = ClassUtils.getUserClass(targetClass);
// The method may be on an interface, but we need attributes from the target class.
// If the target class is null, the method will be unchanged.
Method specificMethod = ClassUtils.getMostSpecificMethod(method, userClass);
// If we are dealing with method with generic parameters, find the original method.
specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
// First try is the method in the target class.
TransactionAttribute txAtt = findTransactionAttribute(specificMethod);
if (txAtt != null) {
return txAtt;
}
// Second try is the transaction attribute on the target class.
txAtt = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAtt != null && ClassUtils.isUserLevelMethod(method)) {
return txAtt;
}
if (specificMethod != method) {
// Fallback is to look at the original method.
txAtt = findTransactionAttribute(method);
if (txAtt != null) {
return txAtt;
}
// Last fallback is the class of the original method.
txAtt = findTransactionAttribute(method.getDeclaringClass());
if (txAtt != null && ClassUtils.isUserLevelMethod(method)) {
return txAtt;
}
}
return null;
}
解析的步骤不是重点,重点是如何去解析.
可以看到这边会拿到注解,然后循环查找合适的事务注解去解析并返回.
我们刚才看到在 AnnotationTransactionAttributeSource中会初始化SpringTransactionAnnotationParser对象
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement ae) {
if (ae.getAnnotations().length > 0) {
for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae);
if (attr != null) {
return attr;
}
}
}
return null;
}
这边即通过SpringTransactionAnnotationParser来解析@Trasation注解,看一下代码即可,不重点分析
@Override
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ae, Transactional.class);
if (attributes != null) {
return parseTransactionAnnotation(attributes);
}
else {
return null;
}
}
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"));
ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<RollbackRuleAttribute>();
Class<?>[] rbf = attributes.getClassArray("rollbackFor");
for (Class<?> rbRule : rbf) {
RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
String[] rbfc = attributes.getStringArray("rollbackForClassName");
for (String rbRule : rbfc) {
RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
Class<?>[] nrbf = attributes.getClassArray("noRollbackFor");
for (Class<?> rbRule : nrbf) {
NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
String[] nrbfc = attributes.getStringArray("noRollbackForClassName");
for (String rbRule : nrbfc) {
NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
rbta.getRollbackRules().addAll(rollBackRules);
return rbta;
}
2.2 生成代理
上面的步骤结束,已经拿到所有类和方法对应的拦截器数组.即生成代理.
这边不赘述,参考另一篇博文:Spring代理创建和代理实现
4. 事务拦截器
2.1 需要懂的事务相关的几个类
3.1 事务信息承载器:TransactionInfo
看一下注释的内容:
- Opaque object used to hold Transaction information. Subclasses must pass it back to methods on this class, but not see its internals.
这个类其实是用来承载解析出来的事务属性集、事务状态的类。记录事务的信息主要是在事务执行的生命周期中,Spring可以把控当前事务。他的内部包含了下面几个类。
protected final class TransactionInfo {
private final PlatformTransactionManager transactionManager;
private final TransactionAttribute transactionAttribute;
private final String joinpointIdentification;
private TransactionStatus transactionStatus;
private TransactionInfo oldTransactionInfo;
}
3.2 事务属性:TransactionAttribute
刚才上面的解析器Parse代码里面已经说明,这个类是用来承载**@Transaction**注解带来的属性的.
3.3 事务状态:TransactionStatus
这个接口是操作事务最关键的类,它能够实现保存点操作、判断事务状态等.具体实现在后面的描述中给出
看一下接口上的注释:
- programmatically request a rollback (instead of throwing an exception that causes an implicit rollback).
- Derives from the SavepointManager interface to provide access to savepoint management facilities. Note that savepoint management is only available if supported by the underlying transaction manager.
2.2 事务拦截器实现
事务拦截器实现了MethodInterceptor,上面生成代理的时候会把TransactionInterceptor添加到对应calss的method中.
现在分析一下他的实现:
关注invoke方法:
@Override
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();
}
});
}
重写了proceedWithInvocation()方法,调用传入的MethodInvocation的proceed方法.
可以这样理解,传进来的MethodInvoke代表某个正在执行的业务方法或者事务(嵌套事务),那么事务执行的操作应该是这样的
{
事务开始
try{
执行业务方法、或者嵌入事务.
}catch{
回滚操作
}finally{
事务提交、状态清除等.
}
}
我们具体看一下代码:
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);
//声明式事务
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
//开启事务
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) {
//事务回滚
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
//清理操作
cleanupTransactionInfo(txInfo);
}
//事务提交
commitTransactionAfterReturning(txInfo);
return retVal;
}
else {
//编程式事务不管
try {
Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,
new TransactionCallback<Object>() {
}
}
}
}
我们从上面代码可以看到基本是这样的情况,这边只分析声明式事务的处理.
3.1 构造事务信息承载器:TransactionInfo
事务信息承载,最重要的是TransationStatus,所以这边的代码分两个步骤:
- 获取TransationStatus
- 构造TransactionInfo
protected TransactionInfo createTransactionIfNecessary(
PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) {
// If no name specified, apply method identification as transaction name.
if (txAttr != null && txAttr.getName() == null) {
txAttr = new DelegatingTransactionAttribute(txAttr) {
@Override
public String getName() {
return joinpointIdentification;
}
};
}
//获取事务状态
TransactionStatus status = null;
if (txAttr != null) {
if (tm != null) {
status = tm.getTransaction(txAttr);
}
else {
//日志
}
}
//构造TransactionInfo
return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}
3.2 获取TransationStatus
这边通过传入的TransationAttribute实现事务的管理。分为三个重要的步骤:拿到事务对象、判断当前存在事务和不存在事务
@Override
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
//拿到事务对象
Object transaction = doGetTransaction();
//存在事务
if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
return handleExistingTransaction(definition, transaction, debugEnabled);
}
//是否超时
if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
}
//不存在事务
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
}
try {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
//开始事务
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
catch (RuntimeException ex) {
resume(null, suspendedResources);
throw ex;
}
catch (Error err) {
resume(null, suspendedResources);
throw err;
}
}
else {
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
}
}
4.1 拿到事务对象
设置保存点,获取相应资源
@Override
protected Object doGetTransaction() {
DataSourceTransactionObject txObject = new DataSourceTransactionObject();
txObject.setSavepointAllowed(isNestedTransactionAllowed());
ConnectionHolder conHolder =
(ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);
txObject.setConnectionHolder(conHolder, false);
return txObject;
}
4.2 存在事务
存在事务的情况,这边会根据Spring定义的事务的传播状态去处理,分别为:
- 不支持事务:报错
- 执行非事务处理,如果存在的话,暂停当前事务(挂起)
- 如果新事务的传播机制是RequireNew,把正在执行的事务挂起.
- 嵌入式事务
- 支持设置保存点,创建保存点
- 不支持设置保存点,挂起当前事务执行新事务
保存点可以通过Connection来处理,这边不关心底层的实现
private TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction, boolean debugEnabled)
throws TransactionException {
//不支持事务:报错
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException(
"Existing transaction found for transaction marked with propagation 'never'");
}
//执行非事务处理,如果存在的话,暂停当前事务(挂起)
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
Object suspendedResources = suspend(transaction);
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(
definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}
//如果新事务的传播机制是RequireNew,把正在执行的事务挂起.
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
catch (RuntimeException beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
catch (Error beginErr) {
resumeAfterBeginException(transaction, suspendedResources, beginErr);
throw beginErr;
}
}
//嵌入式事务 支持设置保存点,创建保存点
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
if (!isNestedTransactionAllowed()) {
throw new NestedTransactionNotSupportedException(
"Transaction manager does not allow nested transactions by default - " +
"specify 'nestedTransactionAllowed' property with value 'true'");
}
if (useSavepointForNestedTransaction()) {
DefaultTransactionStatus status = prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
status.createAndHoldSavepoint();
return status;
}
else {
//不支持设置保存点,挂起当前事务执行新事务
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, null);
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
}
//..............略
}
5.1 设置Spring管理Connection及属性
doBegin方法获取连接,交由Spring管理,主要关注DataSourceTransactionManager这个类的具体实现包括下面几个部分:
- 尝试获取连接,获取不到则创建连接
- 设置事务隔离级别
- 更改自动提交设置,将提交给Spring实现
- 激活事务、设置超时时间
- 将连接绑定到当前线程
- 如果异常,释放连接
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null;
try {
//尝试获取连接,获取不到则创建连接
if (txObject.getConnectionHolder() == null || txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
Connection newCon = this.dataSource.getConnection();
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = txObject.getConnectionHolder().getConnection();
//设置事务隔离级别
Integer previousIsolationLevel = org.springframework.jdbc.datasource.DataSourceUtils.prepareConnectionForTransaction(con, definition);
txObject.setPreviousIsolationLevel(previousIsolationLevel);
//更改自动提交设置,将提交给Spring实现
if (con.getAutoCommit()) {
txObject.setMustRestoreAutoCommit(true);
con.setAutoCommit(false);
}
//激活事务、设置超时时间
txObject.getConnectionHolder().setTransactionActive(true);
int timeout = determineTimeout(definition);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
}
if (txObject.isNewConnectionHolder()) {
//将连接绑定到当前线程
TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());
}
}
catch (Throwable ex) {
if (txObject.isNewConnectionHolder()) {
//异常释放连接
org.springframework.jdbc.datasource.DataSourceUtils.releaseConnection(con, this.dataSource);
txObject.setConnectionHolder(null, false);
}
throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
}
}
5.2 将事务信息记录到事务队列管理器
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
/**
* 如果是新的事务,要把事务信息记录到事务管理器中
*/
if (status.isNewSynchronization()) {
TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(
definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ?
definition.getIsolationLevel() : null);
TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());
TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());
TransactionSynchronizationManager.initSynchronization();
}
}
4.3 不存在事务
5.1 设置Spring管理Connection及属性
同上
5.2 将事务信息记录到事务队列管理器
同上
3.3 构造TransactionInfo
这边比较关键的一步就是绑定事务到线程.从注释上面看,是为了正确管理,即使没有创建事务的情况。
而bindToThread其实是维护了一个ThreadLocal的变量。
*/
protected TransactionInfo prepareTransactionInfo(PlatformTransactionManager tm,
TransactionAttribute txAttr, String joinpointIdentification, TransactionStatus status) {
//构造TransactionInfo
TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
if (txAttr != null) {
txInfo.newTransactionStatus(status);
}
else {
//日志
}
// We always bind the TransactionInfo to the thread, even if we didn't create
// a new transaction here. This guarantees that the TransactionInfo stack
// will be managed correctly even if no transaction was created by this aspect.
//绑定到线程
txInfo.bindToThread();
return txInfo;
}
2.3 执行相应业务方法
这一步就是方法的调用,没有特别指的分析的地方:
return invocation.proceedWithInvocation();
return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
@Override
public Object proceedWithInvocation() throws Throwable {
return invocation.proceed();
}
});
2.4 事务异常处理
事务异常分成两种情况,如果抛出RunTimeException和Error直接回滚,其他异常会尝试提交
protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) {
/**
* 57.当抛出异常时首先判断当前是否存在事务,这是基本依据
*/
if (txInfo != null && txInfo.hasTransaction()) {
//对于RunTimeException或Error的异常会终止提交
if (txInfo.transactionAttribute.rollbackOn(ex)) {
try {
//回滚操作
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
}
catch (TransactionSystemException ex2) {.//.....略
}
}
//其他的异常依然会操作提交
else {
try {
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
catch (TransactionSystemException ex2) {
//........略}
}
}
}
3.1 事务回滚
事务回滚会先判断状态,如果已经提交(有这种情况?),直接报错,不然利用Connection的Api处理回滚
@Override
public final void rollback(TransactionStatus status) throws TransactionException {
//如果事务已经提交,回滚报错
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
//处理回滚
processRollback(defStatus);
}
回滚分成几种情况
- 通过保存点进行回滚
- 新事务通过Connection的api调用回复
- 其他则设值回滚标识
- 事务处理结束之后的信息清除
private void processRollback(DefaultTransactionStatus status) {
try {
try {
/**
* 自定义触发器的调用,注册参考
* @see TransactionSynchronizationManager#registerSynchronization(TransactionSynchronization)
*/
triggerBeforeCompletion(status);
//通过保存点信息进行回滚
if (status.hasSavepoint()) {
status.rollbackToHeldSavepoint();
}
//如果是新的事务,直接回滚,这边也是通过Connection回滚
else if (status.isNewTransaction()) {
doRollback(status);
}
else if (status.hasTransaction()) {
if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
//标记为回滚状态,下一次执行的时候回滚
doSetRollbackOnly(status);
}
else {
//..............
}
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
}
finally {
//事务处理结束之后的信息清除
cleanupAfterCompletion(status);
}
}
通过保存点回滚也是直接调用Connection的api,如下:
//从保存点回滚
conHolder.getConnection().rollback((Savepoint) savepoint);
//释放保存点
conHolder.getConnection().release((Savepoint) savepoint);
事务处理结束之后的信息清除和事务提交之后的finally操作一样,这边不赘述,往后看
2.5 TransactionInfo清除
重置TransactionInfo
/**
* Reset the TransactionInfo ThreadLocal.
* <p>Call this in all cases: exception or normal return!
*/
protected void cleanupTransactionInfo(TransactionInfo txInfo) {
if (txInfo != null) {
txInfo.restoreThreadLocalStatus();
}
}
2.6 事务提交
事务提交这边也分为几种情况:
- 事务已经提交,报错
- 标记为回滚,调用回滚方法(回滚方法中有一步处理就是设置这个标识)
- 提交
public final void commit(TransactionStatus status) throws TransactionException {
//事务已提交,报错
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
//如果事务中已经被标记为回滚,则不尝试提交,直接回滚。
if (defStatus.isLocalRollbackOnly()) {
processRollback(defStatus);
return;
}
if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
processRollback(defStatus);
if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
throw new UnexpectedRollbackException(
"Transaction rolled back because it has been marked as rollback-only");
}
return;
}
//处理事务提交
processCommit(defStatus);
}
这边主要分成几步:
- 存在保存点,说明有事务没有执行完不提交
- 如果是新事务,说明事务执行完成了,调用Connectio.commit提交事务
- 其他情况不提交,报错回滚或者抛错
- finally清除操作
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
try {
boolean beforeCompletionInvoked = false;
try {
prepareForCommit(status);
triggerBeforeCommit(status);
triggerBeforeCompletion(status);
beforeCompletionInvoked = true;
boolean globalRollbackOnly = false;
if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
globalRollbackOnly = status.isGlobalRollbackOnly();
}
if (status.hasSavepoint()) {
//存在保存点则清除,但不提交事务
status.releaseHeldSavepoint();
}
else if (status.isNewTransaction()) {
//独立新事务的提交---非独立新事物不提交
doCommit(status);
}
try {
triggerAfterCommit(status);
}
finally {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
}
}
finally {
/**
* 83.提交后清除操作
*/
cleanupAfterCompletion(status);
}
}
finally清除操作主要分成下面几步:
- 修改事务状态
- 新事务连接释放
- 如果有事务被挂起,则唤醒对应事务
private void cleanupAfterCompletion(DefaultTransactionStatus status) {
//修改事务状态
status.setCompleted();
if (status.isNewSynchronization()) {
//清除当前事务的同步信息
TransactionSynchronizationManager.clear();
}
if (status.isNewTransaction()) {
//事务连接释放
doCleanupAfterCompletion(status.getTransaction());
}
//如果当前事务执行前有事务被挂起,这边是设置一个Object的属性,这也是事务传播的一个处理
if (status.getSuspendedResources() != null) {
//恢复前一个挂起的事务
resume(status.getTransaction(), (SuspendedResourcesHolder) status.getSuspendedResources());
}
}