1、Spring源代码解析六Spring声明式事务处理Spring源代码解析(六):Spring声明式事务处理我们看看Spring中的事务处理的代码,使用Spring管理事务有声明式和编程式两种方式,声明式事务处理通过AOP的实现把事物管理代码作为方面封装来横向插入到业务代码中,使得事务管理代码和业务代码解藕。在这种方式我们结合IoC容器和Spirng已有的FactoryBean来对事务管理进行属性配置,比如传播行为,隔离级别等。其中最简单的方式就是通过配置TransactionProxyFactoryBean来实现声明式事物; 在整个源代码分析中,我们可以大致可以看到Spring实现声明式事物管
2、理有这么几个部分: * 对在上下文中配置的属性的处理,这里涉及的类是TransactionAttributeSourceAdvisor,这是一个通知器,用它来对属性值进行处理,属性信息放在TransactionAttribute中来使用,而这些属性的处理往往是和对切入点的处理是结合起来的。对属性的处理放在类TransactionAttributeSource中完成。 * 创建事物的过程,这个过程是委托给具体的事物管理器来创建的,但Spring通过TransactionStatus来传递相关的信息。 * 对事物的处理通过对相关信息的判断来委托给具体的事物管理器完成。 我们下面看看具体的实现,在T
3、ransactionFactoryBean中: Java代码 1. publicclassTransactionProxyFactoryBeanextendsAbstractSingletonProxyFactoryBean 2. implementsFactoryBean,BeanFactoryAware 3. /这里是Spring事务处理而使用的AOP拦截器,中间封装了Spring对事务处理的代码来支持声明式事务处理的实现 4. privatefinalTransactionInterceptortransactionInterceptor=newTransactionIntercepto
4、r(); 5. 6. privatePointcutpointcut; 7. 8. /这里Spring把TransactionManager注入到TransactionInterceptor中去 9. publicvoidsetTransactionManager(PlatformTransactionManagertransactionManager) 10. this.transactionInterceptor.setTransactionManager(transactionManager); 11. 12. 13. /这里把在bean配置文件中读到的事务管理的属性信息注入到Trans
5、actionInterceptor中去 14. publicvoidsetTransactionAttributes(PropertiestransactionAttributes) 15. this.transactionInterceptor.setTransactionAttributes(transactionAttributes); 16. 17. 18. .中间省略了其他一些方法. 19. 20. /这里创建SpringAOP对事务处理的Advisor 21. protectedObjectcreateMainInterceptor() 22. this.transactionIn
6、terceptor.afterPropertiesSet(); 23. if(this.pointcut!=null) 24. /这里使用默认的通知器 25. returnnewDefaultPointcutAdvisor(this.pointcut,this.transactionInterceptor); 26. 27. else 28. /使用上面定义好的TransactionInterceptor作为拦截器,同时使用TransactionAttributeSourceAdvisor 29. returnnewTransactionAttributeSourceAdvisor(this.
7、transactionInterceptor); 30. 31. 32. public class TransactionProxyFactoryBean extends AbstractSingletonProxyFactoryBean implements FactoryBean, BeanFactoryAware /这里是Spring事务处理而使用的AOP拦截器,中间封装了Spring对事务处理的代码来支持声明式事务处理的实现 private final TransactionInterceptor transactionInterceptor = new TransactionInte
8、rceptor(); private Pointcut pointcut;/这里Spring把TransactionManager注入到TransactionInterceptor中去 public void setTransactionManager(PlatformTransactionManager transactionManager) this.transactionInterceptor.setTransactionManager(transactionManager); /这里把在bean配置文件中读到的事务管理的属性信息注入到TransactionInterceptor中去 p
9、ublic void setTransactionAttributes(Properties transactionAttributes) this.transactionInterceptor.setTransactionAttributes(transactionAttributes); .中间省略了其他一些方法. /这里创建Spring AOP对事务处理的Advisor protected Object createMainInterceptor() this.transactionInterceptor.afterPropertiesSet(); if (this.pointcut !
10、= null) /这里使用默认的通知器 return new DefaultPointcutAdvisor(this.pointcut, this.transactionInterceptor); else / 使用上面定义好的TransactionInterceptor作为拦截器,同时使用TransactionAttributeSourceAdvisor return new TransactionAttributeSourceAdvisor(this.transactionInterceptor); 那什么时候Spring的TransactionInterceptor被注入到Spring
11、AOP中成为Advisor中的一部分呢?我们看到在TransactionProxyFactoryBean中,这个方法在IOC初始化bean的时候被执行: Java代码 1. publicvoidafterPropertiesSet() 2. . 3. /TransactionProxyFactoryBean实际上使用ProxyFactory完成AOP的基本功能。 4. ProxyFactoryproxyFactory=newProxyFactory(); 5. 6. if(this.preInterceptors!=null) 7. for(inti=0;ithis.preIntercepto
12、rs.length;i+) 8. proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(this.preInterceptorsi); 9. 10. 11. 12. /这里是Spring加入通知器的地方 13. /有两种通知器可以被加入DefaultPointcutAdvisor或者TransactionAttributeSourceAdvisor 14. /这里把Spring处理声明式事务处理的AOP代码都放到ProxyFactory中去,怎样加入advisor我们可以参考ProxyFactory的父类AdvisedSupport(
13、) 15. /由它来维护一个advice的链表,通过这个链表的增删改来抽象我们对整个通知器配置的增删改操作。 16. proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(createMainInterceptor(); 17. 18. if(this.postInterceptors!=null) 19. for(inti=0;ithis.postInterceptors.length;i+) 20. proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(this.post
14、Interceptorsi); 21. 22. 23. 24. proxyFactory.copyFrom(this); 25. 26. /这里创建AOP的目标源 27. TargetSourcetargetSource=createTargetSource(this.target); 28. proxyFactory.setTargetSource(targetSource); 29. 30. if(this.proxyInterfaces!=null) 31. proxyFactory.setInterfaces(this.proxyInterfaces); 32. 33. elseif(
15、!isProxyTargetClass() 34. proxyFactory.setInterfaces(ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass(); 35. 36. 37. this.proxy=getProxy(proxyFactory); 38. public void afterPropertiesSet() . /TransactionProxyFactoryBean实际上使用ProxyFactory完成AOP的基本功能。 ProxyFactory proxyFactory = new Proxy
16、Factory(); if (this.preInterceptors != null) for (int i = 0; i this.preInterceptors.length; i+) proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(this.preInterceptorsi); /这里是Spring加入通知器的地方 /有两种通知器可以被加入DefaultPointcutAdvisor或者TransactionAttributeSourceAdvisor /这里把Spring处理声明式事务处理的AOP代码都放到ProxyF
17、actory中去,怎样加入advisor我们可以参考ProxyFactory的父类AdvisedSupport() /由它来维护一个advice的链表,通过这个链表的增删改来抽象我们对整个通知器配置的增删改操作。 proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(createMainInterceptor(); if (this.postInterceptors != null) for (int i = 0; i this.postInterceptors.length; i+) proxyFactory.addAdvisor(
18、this.advisorAdapterRegistry.wrap(this.postInterceptorsi); proxyFactory.copyFrom(this); /这里创建AOP的目标源 TargetSource targetSource = createTargetSource(this.target); proxyFactory.setTargetSource(targetSource); if (this.proxyInterfaces != null) proxyFactory.setInterfaces(this.proxyInterfaces); else if (!i
19、sProxyTargetClass() proxyFactory.setInterfaces(ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass(); this.proxy = getProxy(proxyFactory); Spring 已经定义了一个transctionInterceptor作为拦截器或者AOP advice的实现,在IOC容器中定义的其他属性比如transactionManager和事务管理的属性都会传到已经定义好的 TransactionInterceptor那里去进行处理。以上反映了基本的Sp
20、ring AOP的定义过程,其中pointcut和advice都已经定义好,同时也通过通知器配置到ProxyFactory中去了。 下面让我们回到TransactionProxyFactoryBean中看看TransactionAttributeSourceAdvisor是怎样定义的,这样我们可以理解具体的属性是怎样起作用,这里我们分析一下类TransactionAttributeSourceAdvisor: Java代码 1. publicclassTransactionAttributeSourceAdvisorextendsAbstractPointcutAdvisor 2. /和其他A
21、dvisor一样,同样需要定义AOP中的用到的Interceptor和Pointcut 3. /Interceptor使用传进来的TransactionInterceptor 4. /而对于pointcut,这里定义了一个内部类,参见下面的代码 5. privateTransactionInterceptortransactionInterceptor; 6. 7. privatefinalTransactionAttributeSourcePointcutpointcut=newTransactionAttributeSourcePointcut(); 8. 9. . 10. /定义的Poi
22、ntCut内部类 11. privateclassTransactionAttributeSourcePointcutextendsStaticMethodMatcherPointcutimplementsSerializable 12. . 13. /方法匹配的实现,使用了TransactionAttributeSource类 14. publicbooleanmatches(Methodmethod,ClasstargetClass) 15. TransactionAttributeSourcetas=getTransactionAttributeSource(); 16. /这里使用Tr
23、ansactionAttributeSource来对配置属性进行处理 17. return(tas!=null&tas.getTransactionAttribute(method,targetClass)!=null); 18. 19. .省略了equal,hashcode,tostring的代码 20. public class TransactionAttributeSourceAdvisor extends AbstractPointcutAdvisor /和其他Advisor一样,同样需要定义AOP中的用到的Interceptor和Pointcut /Interceptor使用传进来
24、的TransactionInterceptor /而对于pointcut,这里定义了一个内部类,参见下面的代码 private TransactionInterceptor transactionInterceptor; private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut(); . /定义的PointCut内部类 private class TransactionAttributeSourcePointcut extends StaticMethod
25、MatcherPointcut implements Serializable . /方法匹配的实现,使用了TransactionAttributeSource类 public boolean matches(Method method, Class targetClass) TransactionAttributeSource tas = getTransactionAttributeSource(); /这里使用TransactionAttributeSource来对配置属性进行处理 return (tas != null & tas.getTransactionAttribute(met
26、hod, targetClass) != null); .省略了equal,hashcode,tostring的代码 这里我们看看属性值是怎样被读入的:AbstractFallbackTransactionAttributeSource负责具体的属性读入任务,我们可以有两种读入方式,比如annotation和直接配置.我们下面看看直接配置的读入方式,在Spring中同时对读入的属性值进行了缓存处理,这是一个decorator模式: Java代码 1. publicfinalTransactionAttributegetTransactionAttribute(Methodmethod,Clas
27、stargetClass) 2. /这里先查一下缓存里有没有事务管理的属性配置,如果有从缓存中取得TransactionAttribute 3. ObjectcacheKey=getCacheKey(method,targetClass); 4. Objectcached=this.cache.get(cacheKey); 5. if(cached!=null) 6. if(cached=NULL_TRANSACTION_ATTRIBUTE) 7. returnnull; 8. 9. else 10. return(TransactionAttribute)cached; 11. 12. 13. else 14. /这里通过对方法和目标对象的信息来计算事务缓存属性 15. TransactionAttributetxAtt=computeTransactionAttribute(method,targetClass); 16. /把得到的事务缓存属性存到缓存中,下次可以直接从缓存中取得。 17. if(txAtt=null) 18. this.cache.put(cacheKey,NULL_TRANSACTION_ATTRIBUTE); 19. 20. else 21.
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1