spring 事务

spring的事务是从TransactionProxyFactoryBean开始的TransactionProxyFactoryBean也是一个FactoryBean

源码如下:

publicclassTransactionProxyFactoryBeanextendsAbstractSingletonProxyFactoryBean

implementsBeanFactoryAware

{

publicTransactionProxyFactoryBean()

{

}

publicvoidsetTransactionManager(PlatformTransactionManagertransactionManager)

{

transactionInterceptor.setTransactionManager(transactionManager);

}

publicvoidsetTransactionAttributes(PropertiestransactionAttributes)

{

transactionInterceptor.setTransactionAttributes(transactionAttributes);

}

publicvoidsetTransactionAttributeSource(TransactionAttributeSourcetransactionAttributeSource)

{

transactionInterceptor.setTransactionAttributeSource(transactionAttributeSource);

}

publicvoidsetPointcut(Pointcutpointcut)

{

this.pointcut=pointcut;

}

publicvoidsetBeanFactory(BeanFactorybeanFactory)

{

transactionInterceptor.setBeanFactory(beanFactory);

}

protectedObjectcreateMainInterceptor()

{

transactionInterceptor.afterPropertiesSet();

if(pointcut!=null)

//设置默认的通知器

returnnewDefaultPointcutAdvisor(pointcut,transactionInterceptor);

else

//使用事务属性通知器

returnnewTransactionAttributeSourceAdvisor(transactionInterceptor);

}

privatefinalTransactionInterceptortransactionInterceptor=newTransactionInterceptor();

privatePointcutpointcut;

}

那么transactionInterceptor这个拦截器是在什么时候启动的。

我们在AbstractSingletonProxyFactoryBean中可以看到产生事务代理对象是在该类中的afterPropertiesSet方法中,其源码如下:

publicvoidafterPropertiesSet()

{

if(target==null)

thrownewIllegalArgumentException("Property'target'isrequired");

if(targetinstanceofString)

thrownewIllegalArgumentException("'target'needstobeabeanreference,notabeannameasvalue");

if(proxyClassLoader==null)

proxyClassLoader=ClassUtils.getDefaultClassLoader();

ProxyFactoryproxyFactory=newProxyFactory();

if(preInterceptors!=null)

{

Objectaobj[];

intk=(aobj=preInterceptors).length;

for(inti=0;i<k;i++)

{

Objectinterceptor=aobj[i];

proxyFactory.addAdvisor(advisorAdapterRegistry.wrap(interceptor));

}

}

//配置通知器

proxyFactory.addAdvisor(advisorAdapterRegistry.wrap(createMainInterceptor()));

if(postInterceptors!=null)

{

Objectaobj1[];

intl=(aobj1=postInterceptors).length;

for(intj=0;j<l;j++)

{

Objectinterceptor=aobj1[j];

proxyFactory.addAdvisor(advisorAdapterRegistry.wrap(interceptor));

}

}

proxyFactory.copyFrom(this);

if(proxyInterfaces!=nullTargetSourcetargetSource=createTargetSource(target);

//设置目标接口

proxyFactory.setTargetSource(targetSource);)

//设置代理接口

proxyFactory.setInterfaces(proxyInterfaces);

else

if(!isProxyTargetClass())

proxyFactory.setInterfaces(ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass(),proxyClassLoader));

proxy=proxyFactory.getProxy(proxyClassLoader);

}

Spring事务处理完成AOP配置的地方,这个afterPropertiesSet方法功能实现如下代码

下面我们分析下事务属性的读入

从TransactionProxyFactoryBean中我们可以看到TransactionAttributeSourceAdvisor,我们以这个类为入口从而了解事务属性是如何注入的

TransactionAttributeSourceAdvisor是一个通知器包含了切面和通知

publicTransactionAttributeSourceAdvisor()

{

pointcut=newTransactionAttributeSourcePointcut(){

protectedTransactionAttributeSourcegetTransactionAttributeSource()

{

returntransactionInterceptor==null?null:transactionInterceptor.getTransactionAttributeSource();

}

finalTransactionAttributeSourceAdvisorthis$0;

{

this$0=TransactionAttributeSourceAdvisor.this;

super();

}

}

;

}

在声明式事务处理中,是通过对目标对象的方法调用拦截实现,这个拦截通过AOP发挥过作用。对于拦截器启动,首先需要对方法调用是否需要拦截器进行判断,而判断的依据是那些在TrasactionProxyFactoryBean中为目标对象设置的事务属性。也就是说需要判断当前的目标方法调用是不是一个配置好的,需要进行事务处理方法调用。具体说,这个匹配判断在TransactionAtrributeSourcePoincut中完成,它的实现如代码如下:

publicbooleanmatches(Methodmethod,ClasstargetClass)

{

TransactionAttributeSourcetas=getTransactionAttributeSource();

returntas==null||tas.getTransactionAttribute(method,targetClass)!=null;

}

在pointcut的matches判断过程中,会用到transactionAttributeSource对象,这个对象是在对TranasactionInterceptor进行依赖注入时就配置好了的。它的设置是在基类TransactionAspectSupport完成的,配置了一个NameMatchTransactionAttributeSource代码如下:

publicvoidsetTransactionAttributes(PropertiestransactionAttributes)

{

NameMatchTransactionAttributeSourcetas=newNameMatchTransactionAttributeSource();

tas.setProperties(transactionAttributes);

transactionAttributeSource=tas;

}

在应用调用目标方法的时候,因为这个目标方法已经被TrasactionProxyFactoryBean代理,所以TrasactionProxyFactoryBean需要判断这个方法是否是事务方法。这个判断的实现,是通过NameMatchTransactionAttributeSource中,能否为这个调用方法事务属性来完成的.具体的实现过程是这样的:首先,使用调用方法作为索引的namemap中去查找相应的事务处理性值,如果能够找到,那么就说明调用方法和事务方法直接对应,如果找不到,那么就会遍历整个nameMap,对保存在其中的每一个方法名,使用PatternMatchUtils进行命名模式上的匹配。这里使用PatternMatchUtils进行匹配,是因为在设置事务方法的时候,就像我们常见的那样,可以不需要为事务设置一个完整的方法名,而是可以通过设置方法名的命名模式来完成,比如可以通过像对通配符*的使用。

我们看下NameMatchTransactionAttributeSource中的setProperties方法

publicvoidsetProperties(PropertiestransactionAttributes)

{

TransactionAttributeEditortae=newTransactionAttributeEditor();

StringmethodName;

TransactionAttributeattr;

for(EnumerationpropNames=transactionAttributes.propertyNames();propNames.hasMoreElements();addTransactionalMethod(methodName,attr))

{

methodName=(String)propNames.nextElement();

Stringvalue=transactionAttributes.getProperty(methodName);

tae.setAsText(value);

attr=(TransactionAttribute)tae.getValue();

}

}

publicTransactionAttributegetTransactionAttribute(Methodmethod,ClasstargetClass)

{

//判断当前目标调用的方法与配置事务方法,是否匹配

StringmethodName=method.getName();

TransactionAttributeattr=(TransactionAttribute)nameMap.get(methodName);

if(attr==null)

{

StringbestNameMatch=null;

for(Iteratoriterator=nameMap.keySet().iterator();iterator.hasNext();)

{

StringmappedName=(String)iterator.next();

if(isMatch(methodName,mappedName)&&(bestNameMatch==null||bestNameMatch.length()<=mappedName.length()))

{

attr=(TransactionAttribute)nameMap.get(mappedName);

bestNameMatch=mappedName;

}

}

}

returnattr;

}

通过以上过程,可以得到与目标对象调用方法相关TransactionAttribute对象,在这个对象中,封装了事务处理的配置。

事务处理拦截器的实现

在完成以上准备工作后,经过TransactionProxyFactoryBean的AOP包装,此时如果对目标对象进行方法调用,其调用起作用对象实际是一个proxy代理对象,对目标对象方法的调用,不会直接作用在TransactionProxyFactoryBean设置的目标对象上,而会被设置的事务处理拦截器,而对于TransactionProxyFactoryBean的AOP实现中,获取Proxy对象的过程,这个过程并不复杂,TransactionProxyFactoryBean作为一个Factorybean,对这个bean对象的引用,是通过调用TransactionProxyFactoryBean的getObject方法来得到的,我们对这个方法已经很熟悉了

publicObjectgetObject()

{

if(proxy==null)

thrownewFactoryBeanNotInitializedException();

else

returnproxy;

}

关于如何对AOP代理作用可以看下spring中AOP源码的分析,我们可以注意下TransactionInteceptor中的invoke方法其源码如下:

publicObjectinvoke(finalMethodInvocationinvocation)throwsThrowable{

//这里得到目标对象

ClasstargetClass=(invocation.getThis()!=null?invocation.getThis().getClass():null);

//这里同样的通过判断是否能够得到TransactionAttribute来决定是否对当前方法进行事务处理,有可能该属性已经被缓存,

//具体可以参考上面对getTransactionAttribute的分析,同样是通过TransactionAttributeSource

finalTransactionAttributetxAttr=

getTransactionAttributeSource().getTransactionAttribute(invocation.getMethod(),targetClass);

finalStringjoinpointIdentification=methodIdentification(invocation.getMethod());

//这里判断我们使用了什么TransactionManager

if(txAttr==null||!(getTransactionManager()instanceofCallbackPreferringPlatformTransactionManager)){

//这里创建事务,同时把创建事务过程中得到的信息放到TransactionInfo中去

TransactionInfotxInfo=createTransactionIfNecessary(txAttr,joinpointIdentification);

ObjectretVal=null;

try{

retVal=invocation.proceed();

}

catch(Throwableex){

//targetinvocationexception

completeTransactionAfterThrowing(txInfo,ex);

throwex;

}

finally{

cleanupTransactionInfo(txInfo);

}

commitTransactionAfterReturning(txInfo);

returnretVal;

}

else{

//使用的是Spring定义的PlatformTransactionManager同时实现了回调接口,我们通过其回调函数完成事务处理,就像我们使用编程式事务处理一样。

try{

Objectresult=((CallbackPreferringPlatformTransactionManager)getTransactionManager()).execute(txAttr,

newTransactionCallback(){

publicObjectdoInTransaction(TransactionStatusstatus){

//同样的需要一个TransactonInfo

TransactionInfotxInfo=prepareTransactionInfo(txAttr,joinpointIdentification,status);

try{

returninvocation.proceed();

}

});

}

}

在invoke方法中我们可以看到,首先先获得调用方法的事务处理配置,在得到事务处理配置以后,会取得PlatformTranasctionManager由这个事务处理器来实现事务的创建、提交、回滚操作。PlatformTranasctionManager是在IOC容器中配置的。我们比较熟悉有DataSourceTransactionManager和HiberanteTransactionManager等。

相关推荐