概述
TransactionInterceptor
是Spring
框架内置实现的一个MethodInterceptor
,用于声明式事务管理,使用Spring
事务基础设施org.springframework.transaction.PlatformTransactionManager
。
作为一个MethodInterceptor
,TransactionInterceptor
会被包裹在使用了事务注解的bean
组件外面形成该组件的代理对象,当调用相应使用事务注解的方法时,TransactionInterceptor
的方法拦截器逻辑会被应用,从而完成相应的事务管理。
TransactionInterceptor
继承自TransactionAspectSupport
。主要的事务管理逻辑实现在该基类中。TransactionInterceptor
自身主要是实现接口MethodInterceptor
定义的方法invoke
,触发被TransactionAspectSupport
事务拦截逻辑包围的目标方法的调用。
关于TransactionInterceptor
如何被引入到应用,ProxyTransactionManagementConfiguration
是一个很好的例子。在该配置类中,TransactionInterceptor
被作为一个bean
定义注册到容器,它会被ProxyTransactionManagementConfiguration
注册到容器的另外一个bean transactionAdvisor
使用;应用启动时Spring
的自动代理机制会发现transactionAdvisor
以及它所使用的TransactionInterceptor
,并将该TransactionInterceptor
在创建相应bean
的代理对象时包裹到bean
外部。
源代码解析
spring-tx-5.1.5.RELEASE
package org.springframework.transaction.interceptor;
// 省略 import 行
@SuppressWarnings("serial")
public class TransactionInterceptor extends TransactionAspectSupport
implements MethodInterceptor, Serializable {
/**
* Create a new TransactionInterceptor.
* <p>Transaction manager and transaction attributes still need to be set.
* @see #setTransactionManager
* @see #setTransactionAttributes(java.util.Properties)
* @see #setTransactionAttributeSource(TransactionAttributeSource)
*/
public TransactionInterceptor() {
}
/**
* Create a new TransactionInterceptor.
* @param ptm the default transaction manager to perform the actual transaction management
* @param attributes the transaction attributes in properties format
* @see #setTransactionManager
* @see #setTransactionAttributes(java.util.Properties)
*/
public TransactionInterceptor(PlatformTransactionManager ptm, Properties attributes) {
setTransactionManager(ptm);
setTransactionAttributes(attributes);
}
/**
* Create a new TransactionInterceptor.
* @param ptm the default transaction manager to perform the actual transaction management
* @param tas the attribute source to be used to find transaction attributes
* @see #setTransactionManager
* @see #setTransactionAttributeSource(TransactionAttributeSource)
*/
public TransactionInterceptor(PlatformTransactionManager ptm, TransactionAttributeSource tas) {
setTransactionManager(ptm);
setTransactionAttributeSource(tas);
}
// MethodInterceptor 接口所定义的方法
@Override
@Nullable
public Object invoke(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...
// 使用事务拦截逻辑包围目标方法的调用,从而起到事务管理的效果
// 方法 invokeWithinTransaction 由基类 TransactionAspectSupport 提供实现
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
//---------------------------------------------------------------------
// Serialization support
//---------------------------------------------------------------------
private void writeObject(ObjectOutputStream oos) throws IOException {
// Rely on default serialization, although this class itself doesn't carry state anyway...
oos.defaultWriteObject();
// Deserialize superclass fields.
oos.writeObject(getTransactionManagerBeanName());
oos.writeObject(getTransactionManager());
oos.writeObject(getTransactionAttributeSource());
oos.writeObject(getBeanFactory());
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Rely on default serialization, although this class itself doesn't carry state anyway...
ois.defaultReadObject();
// Serialize all relevant superclass fields.
// Superclass can't implement Serializable because it also serves as base class
// for AspectJ aspects (which are not allowed to implement Serializable)!
setTransactionManagerBeanName((String) ois.readObject());
setTransactionManager((PlatformTransactionManager) ois.readObject());
setTransactionAttributeSource((TransactionAttributeSource) ois.readObject());
setBeanFactory((BeanFactory) ois.readObject());
}
}