Spring 事务源码解析

缘起

一直拿Spring当工具使用, 但是Spring属于那种所有java程序员天天在用(不夸张的说, java生态几乎就是Spring生态),但是细问原理都懵逼的东西. 一直觉得只有Spring的ioc+aop+事务 这三个东西都弄懂了,Spring才算入了门. 也开始了真正java高级程序员之路. 遂下决心要弄清这三个东西的源码. 关于ioc+aop 在【1】中已经浅析了一把. 现在开始弄懂事务.

分析

本文以注解版的事务(即java config 而不是 xml config 为例)为例(参见【2】,数据库是mysql5.7.23),其实分析到最后你会发现,和Spring-AOP的原理很像.

都是注册一个bean的后置处理器,然后该后置处理器为我们生成一个代理对象放进容器中(没错,其实你拿到的开启了事务的service层都是代理对象),代理对象中由MethodInterceptor们构成(拦截器栈),这些拦截器栈对原对象进行增强,而这里的增强是事务(开启事务,提交事务或者回滚事务). 而真正代理对象执行目标方法就是执行这个拦截器链, 拦截器链中的一个环节就是做开启事务,提交事务或者如果异常的话回滚事务(由事务管理器来做. 所以从ioc中获取事务管理器).

下面结合源码进行分析

结合 【2】, 我们的切入点和【1】一样,分析一下

@EnableTransactionManagement 注解做了什么?

1
2
3
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
...

可见,导入了TransactionManagementConfigurationSelector这个类.

这个类是一个ImportSelector, 所以需要覆写 selectImports 方法导入需要导入的类

我们考察TransactionManagementConfigurationSelector.selectImports

1
2
3
4
5
6
7
8
9
10
11
12
13
@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;
}
}

​ 源码1

别的先不说,结合【2】中的代码,我们想知道adviceMode是什么值? 注意到@EnableTransactionManagement中有一个属性

1
2
// Indicate how transactional advice should be applied.
AdviceMode mode() default AdviceMode.PROXY;

​ 源码2

所以我们猜测源码1中的adviceMode是PROXY. 所以走的是源码1的第5行代码. 即@EnableTransactionManagement 这个注解向ioc中引入了两个类

  1. AutoProxyRegistrar
  2. ProxyTransactionManagementConfiguration

而第一个是一个ImportBeanDefinitionRegistrar,这个接口是Spring用于向ioc中注册bean定义用的(进而注册bean). 所以我们看看它的registerBeanDefinitions方法的源码

1
2
3
4
5
6
7
8
9
10
11
12
13
...
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;
}
}
}
...

​ 源码3

其中第二行的mode就是源码2中的mode. 即是PROXY. 所以源码3会走第八行. 等一下,看一下至今为止的调用栈.

目前是从org.springframework.context.support.AbstractApplicationContext.refresh() 的

1
2
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);

​ 源码4

出发的, 熟悉吗? 和【1】中说的一样,源码4中就是干注册bean定义的. 和这里的registerBeanDefinitions方法名不谋而合.

回到源码3的第八行代码. 跟进去,跟了几步之后, 来到了 org.springframework.aop.config.AopConfigUtils.registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry, Object). 其源码如下

1
2
3
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}

​ 源码5

从源码5明显可以看出,注册了一个InfrastructureAdvisorAutoProxyCreator到ioc中去. 和【1】对比,【1】中注册了AnnotationAwareAspectJAutoProxyCreator. 这里注册的是InfrastructureAdvisorAutoProxyCreator.

我们来看看InfrastructureAdvisorAutoProxyCreator是什么东西

发现他实现了 SmartInstantiationAwareBeanPostProcessor 接口和BeanFactoryAware接口. 和【1】中的AnnotationAwareAspectJAutoProxyCreator是一样的.

即我们注册了一个BeanPostProcessor的定义进入ioc. 然后和【1】的分析一样,在refresh方法中的

1
2
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);

中注册这个BeanPostProcessor. 源码在【1】中已经跟过了. 注册好了这个后置bean处理器之后. 它就会拦截在

refresh方法中的

1
2
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

然后是

org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(ConfigurableListableBeanFactory) 中的

1
2
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();

最后一路来到了

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(String, RootBeanDefinition, Object[])

1
2
3
4
5
6
7
8
9
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
...
Object beanInstance = doCreateBean(beanName, mbdToUse, args);

​ 源码8

第3行先拦截一道——就像他的注释说的——给BeanPostProcessor(包括上面我们创建的InfrastructureAdvisorAutoProxyCreator)一个机会,看看能不能创建一个代理,如果能创建,就直接返回了. 而不会进到源码9的doCreateBean(即不会去创建bean).

这一点和【1】的源码19 是一样的(什么叫一样的? 明明就是【1】的源码19好吗? 手动笑哭). 我们再过一遍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); // 遍历调用后置处理器的postProcessBeforeInstantiation方法
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); // 遍历调用后置处理器的postProcessAfterInstantiation方法,但是如果上面的postProcessBeforeInstantiation不成功的话,这里也别调用了
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}

​ 源码6

跟进源码6的第八行.

1
2
3
4
5
6
7
8
9
10
11
12
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}

​ 源码7

源码7的第2行的getBeanPostProcessors() 得到的是目前ioc容器中的bean后置处理器. 目前有8个

1
2
3
4
1.org.springframework.context.support.ApplicationContextAwareProcessor@49c66ade
2.org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor@1fb669c3, 3.org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker@6239aba6
4.InfrastructureAdvisorAutoProxyCreator 5.org.springframework.context.annotation.CommonAnnotationBeanPostProcessor@3e6104fc, 6.org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor@12359a82, 7.org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor@68df9280
8.org.springframework.context.support.ApplicationListenerDetector@3f0ee7cb]

其中就有我们之前注册进入ioc的InfrastructureAdvisorAutoProxyCreator.

那我们希望InfrastructureAdvisorAutoProxyCreator能生成一个代理对象直接返回咯? 但是和【1】的源码19之后的分析(【1】中搜索”失落”就知道了)一样——并不能~ 所以回到源码8,依旧老老实实的走第九行创建bean.

然后就走【1】中的源码12的第六行——initializeBean. 此时就要走【1】中的源码14了. 然后是源码15注入beanFactory. 然后是【1】的源码16. 然后是【1】的源码17——即拿出所有BeanPostProcessor,跑一遍它的postProcessBeforeInitialization方法,我们要关注的是InfrastructureAdvisorAutoProxyCreator这个BeanPostProcessor的postProcessBeforeInitialization方法.

同【1】中的AnnotationAwareAspectJAutoProxyCreator,InfrastructureAdvisorAutoProxyCreator的postProcessBeforeInitialization方法也是平凡的——直接return bean. 所以我们的注意力集中在它的postProcessAfterInitialization方法上(其实和【1】一样,是父类AbstractAutoProxyCreator的方法).

我们再来过一遍

1
2
3
4
5
6
7
8
9
10
@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;
}

​ 源码9

源码9中的 cacheKey是userService(因为不是工厂Bean,即没有实现FactoryBean接口). 我们跟进源码9的第6行org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(Object, String, Object)

1
2
3
4
5
6
7
8
9
// Create proxy if we have advice.
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;
}

​ 源码10

注释也写的很明白——这个代码就是创建代理的. 前提是第二行的specificInterceptors等于DO_NOT_PROXY(即null,即不要代理).

debug发现,它不为null,仅有一个元素

1
[org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor: advice org.springframework.transaction.interceptor.TransactionInterceptor@68702e03]

即有一个TransactionInterceptor!!! 这玩意什么时候进来的?

还记得我们一开始说的 @EnableTransactionManagement 注解引入的东西吗? 上面只分析了一个——AutoProxyRegistrar,还有一个是ProxyTransactionManagementConfiguration. 而这个类我们尚未分析.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@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()); // 注入本类第二个@Bean
advisor.setAdvice(transactionInterceptor()); // 注意,这里面有transactionInterceptor这个bean,就是本类的第三个bean,本类的父类AbstractBeanFactoryPointcutAdvisor的toString方法是可以看到这个advice的信息的
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
return advisor;
}

@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource(); // 可以看看这个无参构造器,里面加入了SpringTransactionAnnotationParser、JtaTransactionAnnotationParser、Ejb3TransactionAnnotationParser,而SpringTransactionAnnotationParser的parseTransactionAnnotation方法(这个方法有多个重载)就会解析@Transactional注解的各种属性的
}

@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;
}

}

​ 源码11

我们发现这玩意是个配置类,向ioc中注册了

  1. BeanFactoryTransactionAttributeSourceAdvisor(但是在ioc中的id是org.springframework.transaction.config.internalTransactionAdvisor)
  2. TransactionAttributeSource(这个后面会看到,是用于解析事务注解的)
  3. TransactionInterceptor, 从源码11的第24行,26行知道里面保存了事务属性信息,事务管理器(如果txManager不为空的话) 但是第一个bean的方法中会调用setAdvice方法将第三个bean注入进去,所以这个bean并不会显式的使用, 而是放在第一个bean中进行使用;

这3个bean. 那么这3个bean是如何和源码10的 第二行关联起来的呢? 且听我慢慢道来.

我们把目光回退到源码10的第二行. 跟进去,来到org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(Class<?>, String, TargetSource). 注意,AbstractAdvisorAutoProxyCreator 是InfrastructureAdvisorAutoProxyCreator的父类哦.

1
2
3
4
5
6
7
8
@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();
}

​ 源码12

源码12的第三行就是获取beanClass(这里是class com.yfs.service.UserService)的可用增强器列表(即advisors)而他的算法也很简单,跟进去(下面的方法也是AbstractAdvisorAutoProxyCreator 中的)

1
2
3
4
5
6
7
8
9
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;
}

​ 源码13

算法实现就是先获取所有的候选增强器(findCandidateAdvisors),而findCandidateAdvisors的实现如下

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findCandidateAdvisors()

1
2
3
4
5
6
7
/**
* Find all candidate Advisors to use in auto-proxying.
* @return the List of candidate Advisors
*/
protected List<Advisor> findCandidateAdvisors() {
return this.advisorRetrievalHelper.findAdvisorBeans();
}

​ 源码14

而这里的advisorRetrievalHelper就是在注册(refresh的registerBeanPostProcessors(beanFactory);调用)BeanPostProcessor的时候调用BeanPostProcessor父类AbstractAdvisorAutoProxyCreator的setBeanFactory方法(因为是BeanFactoryAware接口的实现类)的时候调用AbstractAdvisorAutoProxyCreator的initBeanFactory方法的时候注入的.

源码14继续跟进去

org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
String[] advisorNames = null;
synchronized (this) {
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;
}
}
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)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
...
return advisors;
}

​ 源码15

注意源码15的第五行的cachedAdvisorBeanNames, 伊始它是null的,但是userService并不是第一个加载的bean,所以已经通过源码15的第九行从beanFactory中获取(获取的是Advisor接口的,即增强器,或者说是切面类). 所以就能获取到我们在源码11中注入的BeanFactoryTransactionAttributeSourceAdvisor(bean的id叫做org.springframework.transaction.config.internalTransactionAdvisor)。注意,这里顺便说一句 为什么一些BeanPostProcessor(例如这里的InfrastructureAdvisorAutoProxyCreator)要实现BeanFactoryAware接口. 因为它里面要注入beanFactory之后要拿着这个beanFactory干点事情. 这里干的事情就是, 注意源码15第九行的beanFactory. 这是BeanFactoryAdvisorRetrievalHelper的成员属性,那么这个属性是什么时候传入的呢? 回到源码14,advisorRetrievalHelper是AbstractAdvisorAutoProxyCreator的成员属性,在AbstractAdvisorAutoProxyCreator的如下方法中初始化(传入).

1
2
3
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
}

而initBeanFactory是在setBeanFactory方法中调用的. 熟悉吗? 所以在注入 Bean后置处理器(InfrastructureAdvisorAutoProxyCreator)的时候,通过调用(其父类AbstractAdvisorAutoProxyCreator的)setBeanFactory方法再调用InfrastructureAdvisorAutoProxyCreator自己的initBeanFactory方法,而InfrastructureAdvisorAutoProxyCreator自己的initBeanFactory中又调用了父类的AbstractAdvisorAutoProxyCreator的initBeanFactory方法, 然后就初始化了这个BeanFactoryAdvisorRetrievalHelper类型的成员变量advisorRetrievalHelper(里面有了beanFactory)。具体源码如下:

org.springframework.aop.framework.autoproxy.InfrastructureAdvisorAutoProxyCreator.initBeanFactory(ConfigurableListableBeanFactory)

1
2
3
4
5
@Override
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
super.initBeanFactory(beanFactory); // 调用了父类的AbstractAdvisorAutoProxyCreator的initBeanFactory
this.beanFactory = beanFactory;
}

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.initBeanFactory(ConfigurableListableBeanFactory)

1
2
3
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory); // 初始化了父类AbstractAdvisorAutoProxyCreator的成员变量advisorRetrievalHelper,advisorRetrievalHelper里面有了beanFactory,它用于源码15的第九行代码
}

好了,好了,让我们回到源码15(咳咳,源码分析就是这么容易陷进去,所以个人觉得不论是学习源码还是分析源码都要抓住自己关心的问题去看,不然就是乱看,很难有收获的). 我们说到,解析到我们的带事务方法的userService这个bean的时候第五行的cachedAdvisorBeanNames已经有值了. 并且仅有一个是 id为org.springframework.transaction.config.internalTransactionAdvisor的bean. 最后在源码15 的28行,从ioc容器中取出 id为org.springframework.transaction.config.internalTransactionAdvisor的bean(就是源码11分析出来的第一个@Bean)最后返回这个bean, 这就是源码12的第二行返回的增强器candidateAdvisors(切面),然后源码12第三行针对beanClass=class com.yfs.service.UserService过滤candidateAdvisors,得到可适用于beanClass的增强器,即eligibleAdvisors. 至于具体的过滤逻辑,这里还是细跟一下,因为这里有提取事务注解的逻辑.

定位到源码10的第二行, 现在的beanName是userService,跟到源码12的第三行,继而跟到源码13的第三行.

继而跟进到

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(Class<?>, String)

1
2
3
4
5
6
7
8
9
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;
}

​ 源码19

跟进源码19第二行. 来到org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply(List, Class<?>, String)

1
2
3
4
5
6
7
8
9
10
11
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}

​ 源码20

来到源码20的第6行.candidateAdvisors就是前面源码13第二行得到的只有一个元素——BeanFactoryTransactionAttributeSourceAdvisor的列表. beanClass当然是class com.yfs.service.UserService啦. 跟进第六行源码,来到

org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(List, Class<?>)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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;
}

​ 源码21

源码21的第17行,其中hasIntroductions为false(因为candidateAdvisors中没有实现IntroductionAdvisor接口的), clazz=class com.yfs.service.UserService,candidate为BeanFactoryTransactionAttributeSourceAdvisor.

所以eligibleAdvisors有没有东西就看源码21的第18行,跟进之,来到

org.springframework.aop.support.AopUtils.canApply(Advisor, Class<?>, boolean)

1
2
3
4
5
6
7
8
9
10
11
12
13
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;
}
}

​ 源码22

我们说过,hasIntroductions为false,即源码22中的advisor不会是IntroductionAdvisor接口的. 而BeanFactoryTransactionAttributeSourceAdvisor是实现了PointcutAdvisor接口的.

所以进入到源码22的第七行. pca就是BeanFactoryTransactionAttributeSourceAdvisor,它的getPointcut()方法返回的就是BeanFactoryTransactionAttributeSourceAdvisor的pointcut属性,他是一个TransactionAttributeSourcePointcut的匿名内部类. 第七行的入参

hasIntroductions依旧为false

targetClass=class com.yfs.service.UserService

继续跟进来到

org.springframework.aop.support.AopUtils.canApply(Pointcut, Class<?>, boolean)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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 = 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<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;
}

​ 源码23

源码23的第三行得到的pc.getClassFilter() 得到的是StaticMethodMatcherPointcut中的classFilter属性(StaticMethodMatcherPointcut是TransactionAttributeSourcePointcut的父类,注意,前面我们已经说过了pc到底是啥. 它就是BeanFactoryTransactionAttributeSourceAdvisor的pointcut属性). 而这个classFilter属性是ClassFilter.TRUE,顾名思义,就是不论啥来,matches方法返回的都是true, 所以来到源码23的第七行. 而pc.getMethodMatcher()采用的实现是其父类StaticMethodMatcherPointcut的,即

StaticMethodMatcherPointcut.getMethodMatcher

1
2
3
4
@Override
public final MethodMatcher getMethodMatcher() {
return this;
}

​ 源码24

所以源码23的第七行的methodMatcher就是pc自己. 然后我们一路来,最后要判定是否为true的是源码23的第25行. 注意 clazz=com.yfs.service.UserService, 所以跟进源码23的第25行,来到

org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut.matches(Method, Class<?>)(因为methodMatcher=pc就是一个TransactionAttributeSourcePointcut,参见BeanFactoryTransactionAttributeSourceAdvisor的pointcut属性).

1
2
3
4
5
6
7
8
@Override
public boolean matches(Method method, Class<?> targetClass) {
if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
return false;
}
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}

​ 源码25

源码25的第6行执行BeanFactoryTransactionAttributeSourceAdvisor的pointcut属性的定义中的匿名内部类的方法

1
2
3
4
5
6
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};

​ 源码26

第四行返回的就是源码11第一个bean注入的bean,即源码11的第八行. 在源码11的第八行我们也写了注释说这个transactionAttributeSource实际上是AnnotationTransactionAttributeSource里面装配了SpringTransactionAnnotationParser、可能装配了JtaTransactionAnnotationParser和Ejb3TransactionAnnotationParser. 而SpringTransactionAnnotationParser就是用于事务注解的属性解析的. 不信? 往下看哈~

回到源码25的第七行,method自然是public void com.yfs.service.UserService.insert(),targetClass自然是com.yfs.service.UserService, 所以跟进去

来到了org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource.getTransactionAttribute(Method, Class<?>)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@Override
public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}

// First, see if we have a cached value.
Object cacheKey = getCacheKey(method, targetClass);
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
// Value will either be canonical value indicating there is no transaction attribute,
// or an actual transaction attribute.
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
return null;
}
else {
return cached;
}
}
else {
// We need to work it out.
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
// Put it in the cache.
if (txAttr == null) {
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
}
else {
String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
if (txAttr instanceof DefaultTransactionAttribute) {
((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
}
if (logger.isDebugEnabled()) {
logger.debug("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
}
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
}

​ 源码27

和之前的套路一样,第九行先从缓存中获取,第一次肯定没获取到,来到了第22行,于是来到了关键方法computeTransactionAttribute,method自然是insert,targetClass自然是UserService. 跟进去

来到了org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource.computeTransactionAttribute(Method, Class<?>)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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 txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}
...

​ 源码28

来到第16行,就是寻找specificMethod(即insert方法)上的注解信息的 . 跟两步,来到了

org.springframework.transaction.annotation.AnnotationTransactionAttributeSource.determineTransactionAttribute(AnnotatedElement)

1
2
3
4
5
6
7
8
9
10
11
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
if (element.getAnnotations().length > 0) {
for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element);
if (attr != null) {
return attr;
}
}
}
return null;
}

​ 源码29

入参element是public void com.yfs.service.UserService.insert(). 注意,正如源码11的第二个bean所说,AnnotationTransactionAttributeSource中的annotationParsers里面至少有SpringTransactionAnnotationParser. 所以源码29中的第四行for循环就是用SpringTransactionAnnotationParser的parseTransactionAnnotation方法对element=public void com.yfs.service.UserService.insert()进行解析,得到TransactionAttribute. 跟进第四行,来到org.springframework.transaction.annotation.SpringTransactionAnnotationParser.parseTransactionAnnotation(AnnotatedElement)

1
2
3
4
5
6
7
8
9
10
11
@Override
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(
element, Transactional.class);
if (attributes != null) {
return parseTransactionAnnotation(attributes);
}
else {
return null;
}
}

​ 源码30

第三行看到了没? 就是用注解工具类得到element=public void com.yfs.service.UserService.insert()上的@Transactional信息的. 显然insert方法上有这个注解,所以可以得到这个注解信息,然后进到源码30第6行,正式进行@Transactional注解的解析工作.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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;
}

​ 源码31

具体就不跟了,看看就知道是解析一些@Transactional注解中常用的、不常用的属性.

至此,如何得到对userService可用的增强器列表的源码我们就跟完了, 唉,又是一段漫长的时光~ 我们还是

回到源码10的第五行, 我们开始创建代理. 就是 【1】的源码27和源码28.

与【1】一样,看【1】源码28的最后一行. 此时proxyFactory中已经有了advisors,而advisors里面就是上面的源码11中注入的第一个bean,即BeanFactoryTransactionAttributeSourceAdvisor, 它里面有的advice就是TransactionInterceptor. 和【1】的源码28后续分析类似,我们知道返回的是一个cglib增强的带了BeanFactoryTransactionAttributeSourceAdvisor作为增强器的动态代理

和【1】一样,得到的是一堆的拦截器栈构成的动态代理对象. 什么时候生成的呢?怎么生成的呢? 就在 wrapIfNecessary 方法的createProxy(源码9的第六行)的createProxy方法调用(源码10的第五行).

其实大概在这里一点也不奇怪. 这肯定在生成代理的时候创建的呀. 然后一直跟,可以跟到

org.springframework.aop.framework.CglibAopProxy.getProxy(ClassLoader)

里面有一行代码

1
Callback[] callbacks = getCallbacks(rootClass);

这就是获取调用栈,就是你上图看到的一样. 而跟进getCallbacks方法,里面有源码

1
2
3
4
// Parameters used for optimization choices...
boolean exposeProxy = this.advised.isExposeProxy();
// Choose an "aop" interceptor (used for AOP calls).
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

注意,这个this.advised很重要!DynamicAdvisedInterceptor是一个General purpose AOP callback,它的intercept方法中通过proceed调用就开启了拦截器栈.而这个this.advised 就是org.springframework.aop.framework.ProxyFactory,它里面有属性exposeProxy,这个属性是用于决定后续是否将这个代理暴露在AopContext中去的.所以要记得!!!

综上,ioc中放入的就是这样一个由Cglib增强的UserService的动态代理对象而不是原生的UserService类.

既然得到了动态代理对象,和【1】一样,我们继续分析目标方法的执行流程. 即

1
userService.insert();

方法是如何执行的.

和【1】完全一样,来到了 【1】的源码33(即上图中的第一个拦截器DynamicAdvisedInterceptor). 然后按照责任链设计模式开始跑. 而【1】的源码33的第16行的入参chain只有一个拦截器,即TransactionInterceptor(事务拦截器). 这个chain是【1】的源码33的第二行获取的. 获取的源码在【1】的源码34-35 也分析了(因为TransactionInterceptor是MethodInterceptor,所以直接加入chain).

然后在【1】的源码36的最后一行,进入到TransactionInterceptor的invoke方法. 我们跟进TransactionInterceptor.invoke()的源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@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();
}
});
}

​ 源码16

跟进源码16 的第9行, 我们来到了最核心的代码

org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(Method, Class<?>, InvocationCallback)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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;
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 {
...
}
}

​ 源码17

因为【2】中我们使用的事务管理器是DataSourceTransactionManager,而且txAttr=PROPAGATION_REQUIRED,ISOLATION_DEFAULT

关于这一点的源码分析,源码17 的第5行的getTransactionAttributeSource方法返回的就是TransactionInterceptor中的transactionAttributeSource属性,而这个属性就是在源码11的第三个bean中通过set注入的.而set注入的bean就是源码11 的第二个bean——可以理解为@Transactional注解解析器.至于第五行的

getTransactionAttribute方法,跟进到

org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource.getTransactionAttribute(Method, Class<?>) 其实就是源码27.

因为是第二次来了,所以已经在源码27 的第九行的 attributeCache 中缓存好了. 所以直接拿就行了.

所以源码17的第五行得到的txAttr不是null(是PROPAGATION_REQUIRED,ISOLATION_DEFAULT).

所以会走11行.

等一下,在继续分析之前,我们分析一下源码第六行——即如何获取事务管理器. 因为后面我们就会知道,真正做有关事务方面的事情的就是这个事务管理器.

跟进源码17的第六行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
protected PlatformTransactionManager determineTransactionManager(TransactionAttribute txAttr) {
// Do not attempt to lookup tx manager if no tx attributes are set
if (txAttr == null || this.beanFactory == null) {
return getTransactionManager();
}

String qualifier = txAttr.getQualifier();
if (StringUtils.hasText(qualifier)) {
return determineQualifiedTransactionManager(qualifier);
}
else if (StringUtils.hasText(this.transactionManagerBeanName)) {
return determineQualifiedTransactionManager(this.transactionManagerBeanName);
}
else {
PlatformTransactionManager defaultTransactionManager = getTransactionManager();
if (defaultTransactionManager == null) {
defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
if (defaultTransactionManager == null) {
defaultTransactionManager = this.beanFactory.getBean(PlatformTransactionManager.class);
this.transactionManagerCache.putIfAbsent(
DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
}
}
return defaultTransactionManager;
}
}

​ 源码18

第七行的qualifier就是@Transactional注解中的transactionManager属性(你可以看这个属性的官方注释). 一般我们不写, 如果写了,就会直接从ioc中根据这个属性指定的id获取bean. 后面的(源码18 的11行)的transactionManagerBeanName也就是这个transactionManager属性.

所以如果都没指定的话,最后我们来到15行. 然后不断的尝试获取,如果都失败,就来到了源码18的第19行——从ioc容器中获取.最后将获取好的存放进transactionManagerCache中去。

好了,回到源码17的第11行,我们使用我们刚刚获取的事务管理器tm和事务属性txAttr作为入参,至于joinpointIdentification是com.yfs.service.UserService.insert(一个字符串而已).

分析到这里,本质上讲,我们只是从Spring IOC 的角度分析了 Spring 事务是如何工作的. 但是其实我们还没有从AOP的角度——即拦截器栈(尽管只有一个拦截器——TransactionInterceptor)的角度分析Spring-AOP的工作原理.

这是后篇的工作. 文章太长,怕读者厌烦(虽然好像也没几个读者~囧)

参考

【1】https://yfsyfs.github.io/2019/06/13/spring-AOP-%E6%B3%A8%E8%A7%A3%E5%8E%9F%E7%90%86/

【2】https://github.com/yfsyfs/backend/tree/master/spring-annotation-transaction

【3】Spring 源码深度解析 第二版 第十章