本文是笔者阅读Spring源码的记录文章,由于本人技术水平有限,在文章中难免出现错误,如有发现,感谢各位指正。在阅读过程中也创建了一些衍生文章,衍生文章的意义是因为自己在看源码的过程中,部分知识点并不了解或者对某些知识点产生了兴趣,所以为了更好的阅读源码,所以开设了衍生篇的文章来更好的对这些知识点进行进一步的学习。
全集目录:Spring源码分析:全集整理
由于 事务的源码和 前篇的 Aop 源码逻辑很类似,所以本篇中某些内容不会展开去讲解,建议先阅读完 Spring源码分析十一:@AspectJ方式的AOP再来阅读本文会更好理解。
这是一个巨长的篇章…
全集目录如下:
ProxyTransactionManagementConfiguration
代码如下,并没有逻辑,就是将几个Bean注入的到容器中。不过这几个bean可都是关键bean。
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
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.<Integer>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;
}
}
BeanFactoryTransactionAttributeSourceAdvisor
: 事务的增强器,该方法是否开始事务,是否需要代理该类都在该类中判断TransactionAttributeSource
: 保存了事务相关的一些信息资源。TransactionInterceptor
: 事务拦截器,事务生成代理类时使用的代理拦截器,编写了事务的规则public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
@Nullable
private TransactionAttributeSource transactionAttributeSource;
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
@Nullable
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
/**
* Set the transaction attribute source which is used to find transaction
* attributes. This should usually be identical to the source reference
* set on the transaction interceptor itself.
* @see TransactionInterceptor#setTransactionAttributeSource
*/
public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
this.transactionAttributeSource = transactionAttributeSource;
}
/**
* Set the {@link ClassFilter} to use for this pointcut.
* Default is {@link ClassFilter#TRUE}.
*/
public void setClassFilter(ClassFilter classFilter) {
this.pointcut.setClassFilter(classFilter);
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
}
这个根据上面的分析,我们可以知道这个是事务判断的核心,通过 Aop文章的分析我们可以知道,Advisor 判断一个方法是否匹配,是通过其 Pointcut.matchs
属性来判断的。
然后我们通过上面的代码,发现其 Pointcut
的实现类是 TransactionAttributeSourcePointcut
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
protected TransactionAttributeSourcePointcut() {
setClassFilter(new TransactionAttributeSourceClassFilter());
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
// 调用 TransactionAttributeSource.getTransactionAttribute方法来匹配
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
... 省略一些无关代码
/**
* Obtain the underlying TransactionAttributeSource (may be {@code null}).
* To be implemented by subclasses.
*/
@Nullable
protected abstract TransactionAttributeSource getTransactionAttributeSource();
/**
* {@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 {
@Override
public boolean matches(Class<?> clazz) {
// 如果是一些基础类,则返回false
if (TransactionalProxy.class.isAssignableFrom(clazz) ||
PlatformTransactionManager.class.isAssignableFrom(clazz) ||
PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
return false;
}
// 调用 TransactionAttributeSource.isCandidateClass 方法来匹配
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.isCandidateClass(clazz));
}
}
}
Aop中我们总结了 Pointcut 匹配的需要满足下面两个条件:
pc.getClassFilter().matches(targetClass)
返回truepc.getMethodMatcher().matches(method, targetClass)
返回true通过 TransactionAttributeSourcePointcut
的代码我们可以发现,上面两个条件的关键
可以转换成
TransactionAttributeSource.isCandidateClass
方法来匹配TransactionAttributeSource.getTransactionAttribute
方法来匹配而 TransactionAttributeSource
正是我们在 ProxyTransactionManagementConfiguration
中注入的 AnnotationTransactionAttributeSource
。
经过上面的分析,我们知道了主要逻辑在 isCandidateClass
和 getTransactionAttribute
方法中,因此我们下面来看看这两个方法的实现
isCandidateClass
主要是 判断是否是候选类,即当前的的注解解析器annotationParsers
是否可以解析当前类。annotationParsers
的初始化在其构造函数中,在初始化的过程中中添加了 SpringTransactionAnnotationParser
,我们后面的事务注解解析就是通过 SpringTransactionAnnotationParser
进行的解析。
private final Set<TransactionAnnotationParser> annotationParsers;
...
public AnnotationTransactionAttributeSource() {
this(true);
}
...
public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
this.publicMethodsOnly = publicMethodsOnly;
if (jta12Present || ejb3Present) {
this.annotationParsers = new LinkedHashSet<>(4);
this.annotationParsers.add(new SpringTransactionAnnotationParser());
if (jta12Present) {
this.annotationParsers.add(new JtaTransactionAnnotationParser());
}
if (ejb3Present) {
this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
}
}
else {
this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
}
}
@Override
public boolean isCandidateClass(Class<?> targetClass) {
for (TransactionAnnotationParser parser : this.annotationParsers) {
if (parser.isCandidateClass(targetClass)) {
return true;
}
}
return false;
}
getTransactionAttribute
方法的实现在其父类AbstractFallbackTransactionAttributeSource
中 实现的
// 获取事务属性,如果
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// 判断声明类是否是 Object
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.isTraceEnabled()) {
logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
}
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
}
...
// 解析事务注解属性
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// Don't allow no-public methods as required.
// 如果只允许解析public 方法 && 当前方法不是 publissh
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
// 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 方法代表实现类中的方法
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
// First try is the method in the target class.
// 寻找实现类方法的事务属性,即类方法是否有声明事务属性
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}
// Second try is the transaction attribute on the target class.
// 在实现类上是否有事务属性的声明
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
// 如果存在接口方法,则从接口方法中尝试去获取事务属性
if (specificMethod != method) {
// Fallback is to look at the original method.
txAttr = findTransactionAttribute(method);
if (txAttr != null) {
return txAttr;
}
// Last fallback is the class of the original method.
txAttr = findTransactionAttribute(method.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}
// 都没得到则返回没有得到
return null;
}
这里的逻辑还是很清楚的
在上面的代码中,我们注意到一个方法 findTransactionAttribute
。上面代码就是通过 findTransactionAttribute
方法来寻找事务注解属性的。而findTransactionAttribute
的实现在 AnnotationTransactionAttributeSource
中。其实现代码如下
protected TransactionAttribute findTransactionAttribute(Method method) {
return determineTransactionAttribute(method);
}
...
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
for (TransactionAnnotationParser parser : this.annotationParsers) {
TransactionAttribute attr = parser.parseTransactionAnnotation(element);
if (attr != null) {
return attr;
}
}
return null;
}
可以看到 AnnotationTransactionAttributeSource
中获取 事务注解是通过 TransactionAnnotationParser#parseTransactionAnnotation
方法去解析的,而一开始我们就说过annotationParsers
在构造函数中添加了SpringTransactionAnnotationParser
。我们来看看 SpringTransactionAnnotationParser
进行了怎么样的解析
到这里,我们终于看到了事务注解的描述,这里就是解析事务注解的各种属性信息了
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
// 获取事务注解的属性信息
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
element, Transactional.class, false, false);
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"));
List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
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;
}
我们的分析到这里,就已经可以知道了Spring 中对事务注解的解析过程,逻辑基本和 Spring Aop 类似。
@EnableTransactionManagement
通过引入 TransactionManagementConfigurationSelector
注册了 AutoProxyRegistrar
和 ProxyTransactionManagementConfiguration
两个类。AutoProxyRegistrar
中注册了 InfrastructureAdvisorAutoProxyCreator
自动代理创建器InfrastructureAdvisorAutoProxyCreator
中拦截bean的创建过程,通过 BeanFactoryTransactionAttributeSourceAdvisor
来判断bean中是否有事务注解,有则进行代理。在上面的逻辑中,我们似乎没有发现Spring事务代理的具体过程,实际上代理的过程是在 TransactionInterceptor
中。
在 Aop 的分析文章中,我们知道了无论是 Jdk代理还是 Cglib代理,其增强实现都是调用 Advisor 中的Advice
实现。BeanFactoryTransactionAttributeSourceAdvisor
作为 Advisor
的实现类,自然要遵从 Advisor
的处理方式,当代理被调用时会调用这个类的增强方法,也就是此bean 的Advice ,而在解析事务标签是,我们把 TransactionInterceptor
注入到了 BeanFactoryTransactionAttributeSourceAdvisor
中,所以调用事务增强器增强代理类的时会首先执行TransactionInterceptor
进行增强,同时也就是 TransactionInterceptor#invoke
完成了整个事务的逻辑。
所以我们这里自然要看 TransactionInterceptor#invoke
方法。
public Object invoke(MethodInvocation invocation) throws Throwable {
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// 在事务修饰下执行方法
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
可以看到核心逻辑都在 invokeWithinTransaction
方法中,这里调用的 invokeWithinTransaction
方法 实际是 TransactionAspectSupport#invokeWithinTransaction
方法。所以下面我们来看看 TransactionAspectSupport#invokeWithinTransaction
方法的具体实现
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
// 获取事务数据源,这里获取的数据源就是在 TransactionInterceptor 注入的时候的设置的属性transactionAttributeSource = AnnotationTransactionAttributeSource。
// 在 ProxyTransactionManagementConfiguration 中完成
TransactionAttributeSource tas = getTransactionAttributeSource();
// 1. 获取对应的事务属性
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
// 2. 获取一个合适的 TransactionManager
final TransactionManager tm = determineTransactionManager(txAttr);
// 3. 对于反应式事务的处理
// 从Spring Framework 5.2 M2开始,Spring通过ReactiveTransactionManagerSPI 支持响应式/反应式事务管理
if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && KotlinDelegate.isSuspend(method)) {
throw new TransactionUsageException(
"Unsupported annotated transaction on suspending function detected: " + method +
". Use TransactionalOperator.transactional extensions instead.");
}
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(method.getReturnType());
if (adapter == null) {
throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " +
method.getReturnType());
}
return new ReactiveTransactionSupport(adapter);
});
return txSupport.invokeWithinTransaction(
method, targetClass, invocation, txAttr, (ReactiveTransactionManager) tm);
}
// 判断 tm是否是 PlatformTransactionManager 类型,是则强转,不是则抛出异常
PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
// 构造方法的唯一标识( 全路径了类名.方法)
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
// 4. 对不同事务情景的处理
// 声明式事务的处理
// 如果txAttr为空或者tm 属于非CallbackPreferringPlatformTransactionManager,执行目标增强
// 在TransactionManager上,CallbackPreferringPlatformTransactionManager实现PlatformTransactionManager接口,暴露出一个方法用于执行事务处理中的回调
if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
// 5.如果有必要,创建事务信息。主要由于事务的传播属性,所以这里并不一定会创建事务
TransactionInfo txInfo = createTransactionIfNecessary(ptm, 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.
// 6. 执行被增强的方法
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
// 7. 异常回滚
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
// 8. 提交之前清除事务信息
cleanupTransactionInfo(txInfo);
}
if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {
// Set rollback-only in case of Vavr failure matching our rollback rules...
TransactionStatus status = txInfo.getTransactionStatus();
if (status != null && txAttr != null) {
retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
}
}
// 9.提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
// 编程式事务(CallbackPreferringPlatformTransactionManager)的处理。这里的逻辑基本都被封装了
else {
final ThrowableHolder throwableHolder = new ThrowableHolder();
try {
// 直接调用execute 方法。由于事务的提交回滚等操作都已经封装好了,所以这里并没有对事务进行详细的操作。
Object result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {
// 准备事务信息
TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
try {
// 执行方法
Object retVal = invocation.proceedWithInvocation();
if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {
// Set rollback-only in case of Vavr failure matching our rollback rules...
retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
}
return retVal;
}
catch (Throwable ex) {
if (txAttr.rollbackOn(ex)) {
// A RuntimeException: will lead to a rollback.
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
}
else {
throw new ThrowableHolderException(ex);
}
}
else {
// A normal return value: will lead to a commit.
throwableHolder.throwable = ex;
return null;
}
}
finally {
// 清除事务信息
cleanupTransactionInfo(txInfo);
}
});
// Check result state: It might indicate a Throwable to rethrow.
if (throwableHolder.throwable != null) {
throw throwableHolder.throwable;
}
return result;
}
catch (ThrowableHolderException ex) {
throw ex.getCause();
}
catch (TransactionSystemException ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
ex2.initApplicationException(throwableHolder.throwable);
}
throw ex2;
}
catch (Throwable ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
}
throw ex2;
}
}
}
从上面的代码中,我们可以知道Spring支持声明式事务和编程式事务两种处理。两者的实现本质基本相同。在invoke方法中我们也可以看到这两种方式的实现,通常我们使用的都是通过 @Transactional
注解修饰的声明式事务,所以我们下面主要分析 声明式事务 的处理过程。
获取事务属性 TransactionAttribute
,TransactionAttribute
中包含 传播属性,timeout 等事务属性信息。如果是使用 @Transactional
注解,这个解析过程是在AnnotationTransactionAttributeSource#findTransactionAttribute(java.lang.reflect.Method)
中完成,具体看 篇2中有解释。
加载配置中的 TrancationManager
, 事务管理器,是事务实现的基础,我们这里获取到的是 DataSourceTransactionManager
。
对反应式事务的处理。
不同事务处理方式使用不同的逻辑。在上面的代码中主要是两种情况,一是声明式事务,这种情况是通过 @Transactional
注解修饰方法来表示开启事务。另一种情况是编程式事务,即可以通过xml方式或者配置类方式来进行完成事务功能,其实TransactionTemplate
的实现就是编程式事务,但通过 TransactionTemplate
并不会走到这个逻辑,这里的编程式事务应该单独是通过xml或者配置类方式来配置的。
对于声明式事务的处理和编程式事务的处理,区别主要在两点。一是事务属性上,因为编程式事务是不需要事务属性的,二是 TransactionManager
的不同,CallbackPreferringPlatformTransactionManager
实现了 PlatformTransactionManager
接口,暴露了一个方法用于执行事务处理中的回调。所以这两种方式都可以作为事务处理方式的判断。
在目标方法执行前获取事务并收集事务信息。
事务信息与事务属性并不相同,也就是 TransactionInfo
和 TransactionAttribute
并不相同,TransactionInfo
中包含TransactionAttribute
信息,并且处理 TransactionAttribute
之外还有其他事物信息,比如PlatformTransactionManager
以及 TransactionStatus
相关信息。
执行目标方法
如果出现异常,则进行回滚。这里需要注意,默认的情况下只有 RuntimeException
异常才会执行回滚。可以通过 @Transactional(rollbackFor = Exception.class)
的方式来指定触发回滚的异常
提交事务前的事务信息清除
提交事务
若是 编程式事务,则直接执行execute方法即可,这里就不再讲解。
注: PlatformTransactionManager
和 ReactiveTransactionManager
二者都是为了实现事务,PlatformTransactionManager
在内部进行事务执行流程的封装,并且暴露出来一个 execute
方法用于执行事务的具体信息,TransactionTemplate 的声明式事务就是基于此实现的。而 ReactiveTransactionManager
则是比较原始的,需要我们自己来实现事务的整个逻辑。
上面比较笼统的讲了事务的实现,下面们主要分析以下三个方法,也是事务的的关键流程:
由于篇幅问题,这里另开新篇:
敬请期待。。。。
以上:内容部分参考
《Spring源码深度解析》
如有侵扰,联系删除。 内容仅用于自我记录学习使用。如有错误,欢迎指正