事务处理拦截器的设计与实现

pull/21/head
AmyliaY 5 years ago
parent 88ccfa684e
commit 79abd2bfcd

@ -273,4 +273,151 @@ public class NameMatchTransactionAttributeSource implements TransactionAttribute
```
通过以上过程可以得到与目标对象调用方法相关的TransactionAttribute对象在这个对象中封装了事务处理的配置。具体来说在前面的匹配过程中如果匹配返回的结果是null那么说明当前的调用方法不是一个事务方法不需要纳入Spring统一的事务管理中因为它并没有配置在TransactionProxyFactoryBean的事务处理设置中。如果返回的TransactionAttribute对象不是null,那么这个返回的TransactionAttribute对象就已经包含了对事务方法的配置信息对应这个事务方法的具体事务配置也已经读入到TransactionAttribute对象中了为TransactionInterceptor做好了对调用的目标方法添加事务处理的准备。
### 2.3 事务处理拦截器的设计与实现
### 2.3 事务处理拦截器的设计与实现
在完成以上的准备工作后经过TransactionProxyFactoryBean的AOP包装 此时如果对目标对象进行方法调用起作用的对象实际上是一个Proxy代理对象对目标对象方法的调用不会直接作用在TransactionProxyFactoryBean设置的目标对象上而会被设置的事务处理拦截器拦截。而在TransactionProxyFactoryBean的AOP实现中获取Proxy对象的过程并不复杂TransactionProxyFactoryBean作为一个FactoryBean对这个Bean的对象的引用是通过调用其父类AbstractSingletonProxyFactoryBean的getObject()方法来得到的。
```java
public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig
implements FactoryBean<Object>, BeanClassLoaderAware, InitializingBean {
private Object proxy;
// 返回的是一个proxy代理对象这个proxy是ProxyFactory生成的AOP代理
// 已经封装了对事务处理的拦截器配置
public Object getObject() {
if (this.proxy == null) {
throw new FactoryBeanNotInitializedException();
}
return this.proxy;
}
}
```
InvocationHandler的实现类中有一个非常重要的方法invoke()该方法是proxy代理对象的回调方法在调用proxy对象的代理方法时触发这个回调。事务处理拦截器TransactionInterceptor中实现了InvocationHandler的invoke()方法其过程是首先获得调用方法的事务处理配置在得到事务处理配置以后会取得配置的PlatformTransactionManager由这个事务处理器来实现事务的创建、提交、回滚操作。
```java
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
public Object invoke(final MethodInvocation invocation) throws Throwable {
// 得到代理的目标对象,并将事务属性传递给目标对象
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// 在其父类TransactionAspectSupport中进行后续的事务处理
return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
public Object proceedWithInvocation() throws Throwable {
return invocation.proceed();
}
});
}
}
public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
private static final ThreadLocal<TransactionInfo> transactionInfoHolder =
new NamedThreadLocal<TransactionInfo>("Current aspect-driven transaction");
protected Object invokeWithinTransaction(Method method, Class targetClass, final InvocationCallback invocation)
throws Throwable {
// 获取事务属性,如果属性为空,则该方法是非事务性的
final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
final String joinpointIdentification = methodIdentification(method, targetClass);
// 这里区分不同类型的PlatformTransactionManager因为他们的调用方式不同
// 对CallbackPreferringPlatformTransactionManager来说需要回调函数
// 来实现事务的创建和提交而非CallbackPreferringPlatformTransactionManager
// 则不需要
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// 这里创建事务同时把创建事务过程中得到的信息放到TransactionInfo中
// TransactionInfo是保存当前事务状态的对象
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
// 这里的调用使处理沿着拦截器链进行,使最后目标对象的方法得以调用
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// 如果在事务处理方法调用中出现了异常,事务如何进行处理需要
// 根据具体情况考虑回滚或提交
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
// 这里把 与线程绑定的TransactionInfo设置为oldTransactionInfo
cleanupTransactionInfo(txInfo);
}
// 这里通过事务处理器来对事务进行提交
commitTransactionAfterReturning(txInfo);
return retVal;
} else {
// 使用回调的方式来使用事务处理器
try {
Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,
new TransactionCallback<Object>() {
public Object doInTransaction(TransactionStatus status) {
TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
try {
return invocation.proceedWithInvocation();
}
catch (Throwable ex) {
if (txAttr.rollbackOn(ex)) {
// RuntimeException会导致事务回滚
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
}
else {
throw new ThrowableHolderException(ex);
}
}
else {
// 如果正常返回,则提交该事务
return new ThrowableHolder(ex);
}
}
finally {
cleanupTransactionInfo(txInfo);
}
}
});
// Check result: It might indicate a Throwable to rethrow.
if (result instanceof ThrowableHolder) {
throw ((ThrowableHolder) result).getThrowable();
}
else {
return result;
}
}
catch (ThrowableHolderException ex) {
throw ex.getCause();
}
}
}
/**
* 用于保存事务信息的不透明对象。子类必须将其传递回该类上的方法,但看不到其内部。
*/
protected final class TransactionInfo {
private final PlatformTransactionManager transactionManager;
private final TransactionAttribute transactionAttribute;
private final String joinpointIdentification;
private TransactionStatus transactionStatus;
private TransactionInfo oldTransactionInfo;
public TransactionInfo(PlatformTransactionManager transactionManager,
TransactionAttribute transactionAttribute, String joinpointIdentification) {
this.transactionManager = transactionManager;
this.transactionAttribute = transactionAttribute;
this.joinpointIdentification = joinpointIdentification;
}
}
}
```
以事务提交为例简要的说明下该过程。在调用代理的事务方法时因为前面已经完成了一系列AOP配置对事务方法的调用最终启动
TransactionInterceptor拦截器的invoke()方法。在这个方法中首先会读取该事务方法的事务属性配置然后根据事务属性配置以及具体事务处理器的配置来决定采用哪一个事务处理器这个事务处理器实际上是一个PlatformTransactionManager。在确定好具体的事务处理器之后会根据事务的运行情况和事务配置来决定是不是需要创建新的事务。
对于Spring而言事务的管理实际上是通过一个TransactionInfo对象来完成的在该对象中封装了事务对象和事务处理的状态信息这是事务处理的抽象。在这一步完成以后会对拦截器链进行处理因为有可能在该事务对象中还配置了除事务处理AOP之外的其他拦截器。在结束对拦截器链处理之后会对TransactionInfo中的信息进行更新以反映最近的事务处理情况在这个时候也就完成了事务提交的准备通过调用事务处理器PlatformTransactionManager的commitTransactionAfterReturning()方法来完成事务的提交。这个提交的处理过程已经封装在PlatformTransactionManager的事务处理器中了而与具体数据源相关的处理过程最终委托给相关的具体事务处理器来完成比如DataSourceTransactionManager、Hibermate'TransactionManager等。
在这个invoke()方法的实现中可以看到整个事务处理在AOP拦截器中实现的全过程。同时它也是Spring采用AOP封装事务处理和实现声明式事务处理的核心部分。这部分实现是一个桥梁它胶合了具体的事务处理和Spring AOP框架可以看成是一个Spring AOP应用在这个桥梁搭建完成以后Spring事务处理的实现就开始了。
Loading…
Cancel
Save