Spring transactional注解源码分析
创始人
2025-05-31 11:49:40
0

前提

背景知识

  1. 熟悉Spring Bean 生命周期

  1. 了解Spring Aop原理

  1. 总结Spring Aop

maven坐标

引入spring tx模块

        org.springframeworkspring-tx

分析

学习完spring aop知识。我们可以知道他是使用 beanPostProcessor接口postProcessAfterInitialization 方法处理。“如果切面拦截这个类的方法,那么将创建代理”

源码

AbstractAdvisorAutoProxyCreator#findCandidateAdvisors

查找可能的切面

    protected List findCandidateAdvisors() {Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");return this.advisorRetrievalHelper.findAdvisorBeans();}

advisorRetrievalHelper#findAdvisorBean

源码

public List findAdvisorBeans() {// Determine list of advisor bean names, if not cached already.String[] advisorNames = this.cachedAdvisorBeanNames;if (advisorNames == null) {// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let the auto-proxy creator apply to them!advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);this.cachedAdvisorBeanNames = advisorNames;}List advisors = new ArrayList<>();for (String name : advisorNames) {if (isEligibleBean(name)) {if (this.beanFactory.isCurrentlyInCreation(name)) {if (logger.isTraceEnabled()) {logger.trace("Skipping currently created advisor '" + name + "'");}}else {                    advisors.add(this.beanFactory.getBean(name, Advisor.class));                                        }}}return advisors;}

分析

查找ioc容器中类型是Advisor.class的BeanDefinition。并且我们期望bean来自spring-tx模块下。

于是我们发现目标类 BeanFactoryTransactionAttributeSourceAdvisor

问题

BeanFactoryTransactionAttributeSourceAdvisor何时注册到ioc容器呢?

我们全局搜索下BeanFactoryTransactionAttributeSourceAdvisor

发现如下类:

  1. EnableTransactionManagement 是个注解,importTransactionManagementConfigurationSelector

  1. TransactionManagementConfigurationSelector 实现了ImportSelector接口将执行selectImports方法。注册ProxyTransactionManagementConfiguration到ioc容器

  1. ProxyTransactionManagementConfiguration 以编程方式 @Bean注册 BeanFactoryTransactionAttributeSourceAdvisor。

为什么Springboot 没有标记EnableTransactionManagement注解。事务仍然生效了呢?

答:Springboot开启了自动装配。TransactionAutoConfiguration 标记了EnableTransactionManagement注解。

@Configuration(proxyBeanMethods = false)@ConditionalOnBean(TransactionManager.class)@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)public static class EnableTransactionManagementConfiguration {@Configuration(proxyBeanMethods = false)@EnableTransactionManagement(proxyTargetClass = false)@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false")public static class JdkDynamicAutoProxyConfiguration {}@Configuration(proxyBeanMethods = false)@EnableTransactionManagement(proxyTargetClass = true)@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",matchIfMissing = true)public static class CglibAutoProxyConfiguration {}

BeanFactoryTransactionAttributeSourceAdvisor 完成AOP工作

类图

依类图可知:

  1. TransactionInterceptor 实现了Advice接口。 并注入到BeanFactoryTransactionAttributeSourceAdvisor。

  1. TransactionAttributeSourcePointcut实现了Point接口,并注入到BeanFactoryTransactionAttributeSourceAdvisor。

  1. 并且继承了StaticMethodMatcherPointcut 抽象类。而StaticMethodMatcherPointcut.getMethodMatcher方法返回是其自己。

  1. AnnotationTransactionAttributeSource注入到TransactionAttributeSourcePointcut。

ProxyTransactionManagementConfiguration

该配置类将AnnotationTransactionAtrributeSource和TransactionInterceptor 注入到BeanFactoryTransactionAttributeSourceAdvisor。

public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();advisor.setTransactionAttributeSource(transactionAttributeSource);advisor.setAdvice(transactionInterceptor);if (this.enableTx != null) {advisor.setOrder(this.enableTx.getNumber("order"));}return advisor;}@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionAttributeSource transactionAttributeSource() {return new AnnotationTransactionAttributeSource();}@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {TransactionInterceptor interceptor = new TransactionInterceptor();interceptor.setTransactionAttributeSource(transactionAttributeSource);if (this.txManager != null) {interceptor.setTransactionManager(this.txManager);}return interceptor;}}

检查BeanDefinition是否被切面拦截

AopUtils.findAdvisorsThatCanApply

检查目标类是否有被切面拦截!核心是取Advisor.pointCut是否拦截bd的方法。

    public static List findAdvisorsThatCanApply(List candidateAdvisors, Class clazz) {List eligibleAdvisors = new ArrayList<>();boolean hasIntroductions = !eligibleAdvisors.isEmpty();for (Advisor candidate : candidateAdvisors) {if (canApply(candidate, clazz, hasIntroductions)) {eligibleAdvisors.add(candidate);}}return eligibleAdvisors;}public static boolean canApply(Advisor advisor, Class targetClass, boolean hasIntroductions) {if (advisor instanceof PointcutAdvisor) {PointcutAdvisor pca = (PointcutAdvisor) advisor;return canApply(pca.getPointcut(), targetClass, hasIntroductions);}}

AopUtils.canApply

    public static boolean canApply(Pointcut pc, Class targetClass, boolean hasIntroductions) {if (!pc.getClassFilter().matches(targetClass)) {return false;}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;}Set> classes = new LinkedHashSet<>();if (!Proxy.isProxyClass(targetClass)) {classes.add(ClassUtils.getUserClass(targetClass));}classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(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;}

重点在这个Pointcut对象

BeanFactoryTransactionAttributeSourceAdvisor

源码

    private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {@Override@Nullableprotected TransactionAttributeSource getTransactionAttributeSource() {return transactionAttributeSource;}};@Overridepublic Pointcut getPointcut() {return this.pointcut;}/*** Set the {@link ClassFilter} to use for this pointcut.* Default is {@link ClassFilter#TRUE}.*/public void setClassFilter(ClassFilter classFilter) {this.pointcut.setClassFilter(classFilter);}

分析

BeanFactoryTransactionAttributeSourceAdvisor的pointcut 字段实现类是TransactionAttributeSourcePointcut。

TransactionAttributeSourcePointcut

源码

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {protected TransactionAttributeSourcePointcut() {setClassFilter(new TransactionAttributeSourceClassFilter());}/*** {@link ClassFilter} that delegates to {@link TransactionAttributeSource#isCandidateClass}* for filtering classes whose methods are not worth searching to begin with.*/private class TransactionAttributeSourceClassFilter implements ClassFilter {@Overridepublic boolean matches(Class clazz) {if (TransactionalProxy.class.isAssignableFrom(clazz) ||TransactionManager.class.isAssignableFrom(clazz) ||PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {return false;}TransactionAttributeSource tas = getTransactionAttributeSource();return (tas == null || tas.isCandidateClass(clazz));}}

分析

重写了ClassFilter.matchs方法。对应AopUtils.canApply代码。

说明 TransactionAttributeSourceClassFilter#matchs 方法将被执行,最终走到AnnotationTransactionAttributeSource#isCandidateClass 方法。

    if (!pc.getClassFilter().matches(targetClass)) {return false;}

AnnotationTransactionAttributeSource

源码

    private final Set annotationParsers;public AnnotationTransactionAttributeSource() {this(true);}public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {this.publicMethodsOnly = publicMethodsOnly;this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());}@Overridepublic boolean isCandidateClass(Class targetClass) {for (TransactionAnnotationParser parser : this.annotationParsers) {if (parser.isCandidateClass(targetClass)) {return true;}}return false;}

分析

发现isCandidateClass 调用SpringTransactionAnnotationParser.isCandidateClass 方法处理

SpringTransactionAnnotationParser

源码

    @Overridepublic boolean isCandidateClass(Class targetClass) {return AnnotationUtils.isCandidateClass(targetClass, Transactional.class);}

分析

targetClass 是否标记Transactional注解.

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
JAVA多线程知识整理 Java多线程基础 线程的创建和启动 继承Thread类来创建并启动 自定义Thread类的子类&#...
【洛谷 P1090】[NOIP... [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G ...
国民技术LPUART介绍 低功耗通用异步接收器(LPUART) 简介 低功耗通用异步收发器...
城乡供水一体化平台-助力乡村振... 城乡供水一体化管理系统建设方案 城乡供水一体化管理系统是运用云计算、大数据等信息化手段࿰...
程序的循环结构和random库...   第三个参数就是步长     引入文件时记得指明字符格式,否则读入不了 ...
中国版ChatGPT在哪些方面... 目录 一、中国巨大的市场需求 二、中国企业加速创新 三、中国的人工智能发展 四、企业愿景的推进 五、...
报名开启 | 共赴一场 Flu... 2023 年 1 月 25 日,Flutter Forward 大会在肯尼亚首都内罗毕...
汇编00-MASM 和 Vis... Qt源码解析 索引 汇编逆向--- MASM 和 Visual Studio入门 前提知识ÿ...
【简陋Web应用3】实现人脸比... 文章目录🍉 前情提要🌷 效果演示🥝 实现过程1. u...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
windows安装JDK步骤 一、 下载JDK安装包 下载地址:https://www.oracle.com/jav...
分治法实现合并排序(归并排序)... 🎊【数据结构与算法】专题正在持续更新中,各种数据结构的创建原理与运用✨...
在linux上安装配置node... 目录前言1,关于nodejs2,配置环境变量3,总结 前言...
Linux学习之端口、网络协议... 端口:设备与外界通讯交流的出口 网络协议:   网络协议是指计算机通信网...
Linux内核进程管理并发同步... 并发同步并发 是指在某一时间段内能够处理多个任务的能力,而 并行 是指同一时间能够处理...
opencv学习-HOG LO... 目录1. HOG(Histogram of Oriented Gradients,方向梯度直方图)1...
EEG微状态的功能意义 导读大脑的瞬时全局功能状态反映在其电场结构上。聚类分析方法一致地提取了四种头表面脑电场结构ÿ...
【Unity 手写PBR】Bu... 写在前面 前期积累: GAMES101作业7提高-实现微表面模型你需要了解的知识 【技...