Spring源码剖析-事务源码之@Transactionl解析
Posted 墨家巨子@俏如来
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring源码剖析-事务源码之@Transactionl解析相关的知识,希望对你有一定的参考价值。
前言
在上一章我们分析了Spring的AOP的源码,本篇文章是对事务的源码分析,我们都知道事务的管理是基于AOP实现的,所以有了上一篇的铺垫这一章会比较简单一点。
事务的源码我会分两章写,一张写Transcational的解析,一张写事务的执行流程。先上一个图,待会儿可以根据这个图来看源码
事务配置案例
配置事务管理器,开启注解事务支持
<!-- 开启事务支持 -->
<tx:annotation-driven/>
<!-- 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
...省略...
</bean>
标记方法需要事务
public class UserService ...{
//事务注解
@Transactional
public void insert(User user){
...
}
}
事务注解打在方法上,当然也是可以打在类上。
事务注解原理
在Spring中通常有两种方式管理事务,一是使用XML统一配置事务 ,二是通过注解式编程即在对象方法上贴@Trancactional来管理事务,现在用的多的就是注解式编程,所以我们就从这个事务注解开始分析把。
Transactional贴在对象的方法上就可以通过AOP的方式帮我们开启事务,提交事务或是回滚事务操作,不仅简化了我们的工作难度,避免重复事务逻辑处理,同时也减少了代码的侵入,达到代码解耦和的效果。
事务的管理是基于AOP实现,AOP的原理又是动态代理,也就是说被标记了@Transactional的类都会创建代理类来实现事务增强,创建代理后,方法的真实调用都是走代理对象。那么Spring如何知道要对哪些类哪些方法进行代理?Spring会把 @Transactional 注解作为切点,这样就知道哪些方法需要被代理 。至于代理类的创建是在Bean的实例化过程中完成,在上一篇文章有说道,见:《AOP原理》
事务标签解析器
NamespaceHandlerSupport 注册解析器
因为注解事务支持需要在XML中开启 ,所以对于事务来说可以分为两部分 :一是事务配置解析 ,二是代理创建。在上一章节我们就有提到,对于xml中的所有namespace都有对应的解析器, 在Spring中有一个接口叫 NamespaceHandlerSupport ,它提供了Spring xml配置的namespace的解析支持。
NamespaceHandlerSupport
它有一个子类 TxNaespaceHadler
就是针对于事务的 namespace 处理
public class TxNamespaceHandler extends NamespaceHandlerSupport {
static final String TRANSACTION_MANAGER_ATTRIBUTE = "transaction-manager";
//事务管理器默认的名字
static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager";
static String getTransactionManagerName(Element element) {
return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ?
element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME);
}
@Override
public void init() {
registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
}
}
AnnotationDrivenBeanDefinitionParser创建AutoProxyCreator
看得出来上面的 init 方法中注册了一个 AnnotationDrivenBeanDefinitionParser
它就是针对于 <tx:annotation-driven/>
的解析器,并且负责创建事务管理需要的基础类。
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
AnnotationDrivenBeanDefinitionParser() {
}
//解析元素:Element就是 <tx:annotation-driven/>
public BeanDefinition parse(Element element, ParserContext parserContext) {
//注册事务监听
this.registerTransactionalEventListenerFactory(parserContext);
//判断model,默认是proxy,走else
String mode = element.getAttribute("mode");
if ("aspectj".equals(mode)) {
this.registerTransactionAspect(element, parserContext);
} else {
//创建自动代理创建器(InfrastructureAdvisorAutoProxyCreator)
AnnotationDrivenBeanDefinitionParser.AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
}
return null;
}
AopAutoProxyConfigurer 创建事务核心类
这个parse解析方法注册了事务监听器后就判断了mode,默认使用的是proxy代理方式,即调用configureAutoProxyCreator
方法,一路跟下去
/**
* Inner class to just introduce an AOP framework dependency when actually in proxy mode.
*/
private static class AopAutoProxyConfigurer {
public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
//注册一个自动代理创建器 InfrastructureAdvisorAutoProxyCreator
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
//判断容器中是否已经注册了 internalTransactionAdvisor
if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
Object eleSource = parserContext.extractSource(element);
//【标记1】注册 TransactionAttributeSource
// 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);
//【标记2】注册 TransactionInterceptor
// 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);
//【标记3】 注册一个TransactionAttributeSourceAdvisor
// Create the BeanFactoryTransactionAttributeSourceAdvisor 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);
}
}
}
该方法先是创建了一个 InfrastructureAdvisorAutoProxyCreator
代理创建器 ,然后又注册了 AnnotationTransactionAttributeSource
, TransactionInterceptor
,BeanFactoryTransactionAttributeSourceAdvisor
三个Bean , 且前两个Bean被添加到了 BeanFactoryTransactionAttributeSourceAdvisor
中。
-
InfrastructureAdvisorAutoProxyCreator:是BeanPostProcessor的子类,在Bean的初始化之后调用postProcessAfterInitialization方法,目的就是找出增强器为合适的类创建代理。跟上一章节《AOP原理》做的事情差不多
-
AnnotationTransactionAttributeSource : 是专门用于获取基于注解的Spring声明式事务管理的事务属性的属性源,用来读取@Transational注解并进行相关参数封装,用做后续的事务处理。
它除了能处理Transactional注解之外,还支持JTA 1.2的javax.transaction.Transactional事务注解以及EJB3的javax.ejb.TransactionAttribute事务注解
-
TransactionInterceptor:该类实现了TransactionAspectSupport , TransactionAspectSupport 中持有 TransactionManager ,拥有处理事务的能力。同时该类还实现了 MethodInterceptor 接口 ,它也作为AOP的拦截器。拦截器链中每个拦截器都有一个invoke方法,该方法就是对某个方法进行事务增强的入口,因此主要看invoke方法的实现逻辑!
-
BeanFactoryTransactionAttributeSourceAdvisor:它是一个Advisor,用来对事务方法做增强,只要被注解@Transationl的方法都会被增强,该Advisor 包含 AnnotationTransactionAttributeSource 和 TransactionInterceptor ,以及 TransactionAttributeSourcePointcut 。
TransactionAttributeSourcePointcut 是事务属性源匹配器,是BeanFactoryTransactionAttributeSourceAdvisor的切入点,通过它来判断某个bean是否可以被增强
解析当前方法是否要被代理
InfrastructureAdvisorAutoProxyCreator
是一个BeanPostProcessor,当Bean在实例化过程中,会通过AutoProxyCreator的postProcessAfterInitialization
方法来决定是否创建代理,其实就是通过BeanFactoryTransactionAttributeSourceAdvisor
来解析判断该类是否被注解了@Transcational来决定是否创建代理 ,见:AbstractAutoProxyCreator#wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
} else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
} else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
//获取增强器 Advisors
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//创建代理
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
AbstractAdvisorAutoProxyCreator查找增强器
通过调用 AbstractAdvisorAutoProxyCreator#findCandidateAdvisors ,查找增强器 ,通过AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply 来匹配当前类适合的增强器,然后为当前Bean创建代理。这个流程在上一章: 《AOP原理》 已经说过,这里就不细细分析了。见:AbstractAdvisorAutoProxyCreator#findEligibleAdvisors
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//查找所有增强器
List<Advisor> candidateAdvisors = this.findCandidateAdvisors();
//找到当前beanClass适用的增强器
List<Advisor> eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
this.extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = this.sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
我们重点来看一下它是如何匹配适合当前Bean的增强器的。见:
AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply
//搜索能应用于当前beanClass的 Advisors
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
这里的 candidateAdvisors 就是获取到的增强器 ,其中就包括:BeanFactoryTransactionAttributeSourceAdvisor , beanClass是当前要被创建代理的类,然后走的是AopUtils.findAdvisorsThatCanApply 方法查找能匹配当前类的advisors.一路断点跟下去会走到 AopUtils#canApply
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 切点的Advisor
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
AopUtils 查找合适的增强器
继续跟踪 org.springframework.aop.support.AopUtils#canApply(org.springframework.aop.Pointcut, java.lang.Class<?>, boolean)
源码:
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
//class 过滤器 ,默认直接返回true
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
//方法匹配器,其实就是 BeanFactoryTransactionAttributeSourceAdvisor
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;
}
//获取到要被创建代理的原生类的 class,并把其接口添加到classes中
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
//处理classes
for (Class<?> clazz : classes) {
//拿到原生类,或其接口的所有方法声明
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
//通过 MethodMatcher 匹配,走的是 TransactionAttributeSourcePointcut#matches方法
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
该方法的作用是匹配给定的切入点是否完全适用于给定的类,通过MethodMatcher 来匹配,这里的MethodMatcher 本身就是PointBeanFactoryTransactionAttributeSourceAdvisor
,它通过父类TransactionAttributeSourcePointcut#matches
完成匹配,如下:
TransactionAttributeSourcePointcut 查找@Transactional注解
下面是 TransactionAttributeSourcePointcut 进行匹配的源码:
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
@Override
public boolean matches(Method method, @Nullable Class<?> targetClass) {
if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
return false;
}
//获取 BeanFactoryTransactionAttributeSourceAdvisor 中的AnnotationTransactionAttributeSource
TransactionAttributeSource tas = getTransactionAttributeSource();
//判断TransactionAttribute不为空,说明该targetClass的method是有事务注解的
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
这里getTransactionAttributeSource();
方法由子类BeanFactoryTransactionAttributeSourceAdvisor
来实现,目的是获取TransactionAttributeSource
对象,然后调用tas.getTransactionAttribute获取TransactionAttribute,不为空说明方法是支持@Transational的。
tas.getTransactionAttribute
方法中会先通过类名和方法名构建一个key,从缓存中 attributeCache 获取TransactionAttribute,如果没有,就通过AnnotationTransactionAttributeSource#determineTransactionAttribute
去解析当前Method 的@Transactional封装成 TransactionAttribute,并装入缓存。源码如下;
org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#getTransactionAttribute
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}
// First, see if we have a cached value.
//构建一个缓存key
Object cacheKey = getCacheKey(method, targetClass);
//从缓存中获取TransactionAttribute
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 {
//返回缓存中的TransactionAttribute
return cached;
}
}
else {
// We need to work it out.
//查找和解析method的事务注解,封装成TransactionAttribute
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
// Put it in the cache.
if (txAttr == null) {
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
}
else<以上是关于Spring源码剖析-事务源码之@Transactionl解析的主要内容,如果未能解决你的问题,请参考以下文章
Spring源码剖析-Transactional 事务执行流程