Spring AOP实现声明式事务代码分析

 众所周知,Spring的声明式事务是利用AOP手段实现的,所谓“深入一点,你会更快乐”,本文试图给出相关代码分析。

  AOP联盟为增强定义了org.aopalliance.aop.Advice接口,Spring由Advice接口扩展了5中类型的增强(接口),AOP联盟自身提供了IntroductionInterceptor->MethodInterceptor->Interceptor->Advice,而MethodInterceptor就代表环绕增强,表示在目标方法执行前后实施增强。要进行事务操作,正是要在目标方法前后加入相应的代码,因此,Spring为我们提供了TransactionInterceptor类。

  TransactionInterceptor的invoke方法调用了父类TransactionAspectSupport的invokeWithinTransactionf方法,

 

Java代码  

  1. if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {  
  2.             // Standard transaction demarcation with getTransaction and commit/rollback calls.  
  3.             TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);  
  4.             Object retVal = null;  
  5.             try {  
  6.                 // This is an around advice: Invoke the next interceptor in the chain.  
  7.                 // This will normally result in a target object being invoked.  
  8.                 retVal = invocation.proceedWithInvocation();  
  9.             }  
  10.             catch (Throwable ex) {  
  11.                 // target invocation exception  
  12.                 completeTransactionAfterThrowing(txInfo, ex);  
  13.                 throw ex;  
  14.             }  
  15.             finally {  
  16.                 cleanupTransactionInfo(txInfo);  
  17.             }  
  18.             commitTransactionAfterReturning(txInfo);  
  19.             return retVal;  
  20.         }  

 瞬间,我们看到了我们期望看到的代码,其中completeTransactionAfterThrowing里面做的是rollback的相关操作。

 

  Spring 提供了多种不同的方案实现对 bean 的 aop proxy, 包括 ProxyFactoryBean, 便利的 TransactionProxyFactoryBean 以及 AutoProxyCreator 等,

这里重点说一下最常用的 ProxyFactoryBean, TransactionProxyFactoryBean, BeanNameAutoProxyCreator, DefaultAdvisorAutoProxyCreator 的联系和区别   

  

1. ProxyFactoryBean : 使用率最高的 proxy 方式, 它通过配置 interceptorNames 属性决定加入哪些 advisor (method interceptor 将会被自动包装成 advisor),   

注意是 "interceptorNames" 而不是 "interceptors", 

原因是 ProxyFactoryBean 可能返回非 singleton 的 proxy 实例, 而 advisior 可能也是非 singleton 的, 

因此不能通过 interceptor reference 来注入   

  

2. TransactionProxyFactoryBean : 特定用于 transaction proxy, 注意其 super class 是 AbstractSingletonProxyFactoryBean, 也就是说,

TransactionProxyFactoryBean 永远无法返回非 singleton 的 proxy 实例 !

如果你需要非 singleton 的 proxy 实例, 请考虑使用 ProxyFactoryBean.   

  

3. BeanNameAutoProxyCreator : 故名思义, 根据 bean name 进行 auto proxy, bean name 的 match 规则参见 org.springframework.util.PatternMatchUtils   

  

4. DefaultAdvisorAutoProxyCreator : 更强大的 auto proxy creator, 强大之处在于它会 cahce 容器中所有注册的 advisor, 然后搜索容器中所有的 bean ,   

如果某个 bean 满足 advisor 中的 Pointcut, 那么将会被自动代理, 与 BeanNameAutoProxyCreator 相比, 省去了配置 beanNames 的工作, 

 

5. AnnotationAwareAspectJAutoProxyCreator -> @Aspect  <aop:aspectj-autoproxy/>

  -> @Transactinal <tx:annotation-driven transaction-manager="txManager"/>

 

 AbstractAutoProxyCreator实现了BeanPostProcessor,Spring默认会自动创建代理。

Java代码  

  1. // AbstractAutowireCapableBeanFactory  
  2. public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)  
  3.             throws BeansException {  
  4.   
  5.         Object result = existingBean;  
  6.         for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {  
  7.             result = beanProcessor.postProcessBeforeInitialization(result, beanName);  
  8.             if (result == null) {  
  9.                 return result;  
  10.             }  
  11.         }  
  12.         return result;  
  13.     }  
  14.   
  15.     public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)  
  16.             throws BeansException {  
  17.   
  18.         Object result = existingBean;  
  19.         for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {  
  20.             result = beanProcessor.postProcessAfterInitialization(result, beanName);  
  21.             if (result == null) {  
  22.                 return result;  
  23.             }  
  24.         }  
  25.         return result;  
  26.     }  

 

 

我们来看下AbstractAutoProxyCreator里的重点代码

Java代码  

  1. // AbstractAutoProxyCreator  
  2. public Object postProcessBeforeInitialization(Object bean, String beanName) {  
  3.         return bean;  
  4.     }  
  5.   
  6.     /** 
  7.      * Create a proxy with the configured interceptors if the bean is 
  8.      * identified as one to proxy by the subclass. 
  9.      * @see #getAdvicesAndAdvisorsForBean 
  10.      */  
  11.     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  
  12.         if (bean != null) {  
  13.             Object cacheKey = getCacheKey(bean.getClass(), beanName);  
  14.             if (!this.earlyProxyReferences.contains(cacheKey)) {  
  15.                 return wrapIfNecessary(bean, beanName, cacheKey);  
  16.             }  
  17.         }  
  18.         return bean;  
  19.     }  

 

Java代码  

  1. /** 
  2.      * Wrap the given bean if necessary, i.e. if it is eligible for being proxied. 
  3.      * @param bean the raw bean instance 
  4.      * @param beanName the name of the bean 
  5.      * @param cacheKey the cache key for metadata access 
  6.      * @return a proxy wrapping the bean, or the raw bean instance as-is 
  7.      */  
  8.     protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {  
  9.         if (this.targetSourcedBeans.contains(beanName)) {  
  10.             return bean;  
  11.         }  
  12.         if (this.nonAdvisedBeans.contains(cacheKey)) {  
  13.             return bean;  
  14.         }  
  15.         if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {  
  16.             this.nonAdvisedBeans.add(cacheKey);  
  17.             return bean;  
  18.         }  
  19.   
  20.         // Create proxy if we have advice.  
  21.         Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);  
  22.         if (specificInterceptors != DO_NOT_PROXY) {  
  23.                  // 有AnnotationAwareAspectJAutoProxyCreator 这个processor时  
  24.             this.advisedBeans.add(cacheKey);  
  25.             Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));  
  26.             this.proxyTypes.put(cacheKey, proxy.getClass());  
  27.             return proxy;  
  28.         }  
  29.   
  30.         this.nonAdvisedBeans.add(cacheKey);  
  31.         return bean;  
  32.     }  

 

 

Java代码  

  1. protected Object createProxy(  
  2.             Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {  
  3.   
  4.         ProxyFactory proxyFactory = new ProxyFactory();  
  5.         // Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.  
  6.         proxyFactory.copyFrom(this);  
  7.   
  8.         if (!shouldProxyTargetClass(beanClass, beanName)) {  
  9.             // Must allow for introductions; can't just set interfaces to  
  10.             // the target's interfaces only.  
  11.             Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);  
  12.             for (Class<?> targetInterface : targetInterfaces) {  
  13.                 proxyFactory.addInterface(targetInterface);  
  14.             }  
  15.         }  
  16.   
  17.         Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);  
  18.         for (Advisor advisor : advisors) {  
  19.             proxyFactory.addAdvisor(advisor);  
  20.         }  
  21.   
  22.         proxyFactory.setTargetSource(targetSource);  
  23.         customizeProxyFactory(proxyFactory);  
  24.   
  25.         proxyFactory.setFrozen(this.freezeProxy);  
  26.         if (advisorsPreFiltered()) {  
  27.             proxyFactory.setPreFiltered(true);  
  28.         }  
  29.   
  30.         return proxyFactory.getProxy(this.proxyClassLoader);  
  31.     }  

 

至于事务切面和其他切面形成切面chain时的调用关系,请参考http://wely.iteye.com/blog/2313924的解释。

  本文并未介绍事务属性、事务状态、事务管理器以及事务自身更底层的一些内容,这些内容留待我们研究了mysql的事务后再详细介绍。


原文链接:[http://wely.iteye.com/blog/2317428]

时间: 2024-11-01 03:55:36

Spring AOP实现声明式事务代码分析的相关文章

spring声明式事务 同一类内方法调用事务失效

只要避开Spring目前的AOP实现上的限制,要么都声明要事务,要么分开成两个类,要么直接在方法里使用编程式事务 [问题]        Spring的声明式事务,我想就不用多介绍了吧,一句话"自从用了Spring AOP啊,事务管理真轻松啊,真轻松:事务管理代码没有了,脑不酸了,手不痛了,一口气全配上了事务:轻量级,测试起来也简单,嘿!".不管从哪个角度看,轻量级声明式事务都是一件解放生产力的大好事.所以,我们"一直用它".         不过,最近的一个项目里

spring学习笔记(22)声明式事务配置,readOnly无效写无异常

在上一节内容中,我们使用了编程式方法来配置事务,这样的优点是我们对每个方法的控制性很强,比如我需要用到什么事务,在什么位置如果出现异常需要回滚等,可以进行非常细粒度的配置.但在实际开发中,我们可能并不需要这样细粒度的配置.另一方面,如果我们的项目很大,service层方法很多,单独为每个方法配置事务也是一件很繁琐的事情.而且也可能会造成大量重复代码的冗杂堆积.面对这些缺点,我们首要想到的就是我们spring中的AOP了.spring声明式事务的实现恰建立在AOP之上. 在这一篇文章中,我们介绍s

SpringMVC+Spring+Mybatis整合,使用druid连接池,声明式事务,maven配置

一直对springmvc和mybatis挺怀念的,最近想自己再搭建下框架,然后写点什么. 暂时没有整合缓存,druid也没有做ip地址的过滤.Spring的AOP简单配置了下,也还没具体弄,不知道能不能用,log也不知道能不能用,`(*∩_∩*)′哈哈,有点不负责任...... 2014-08-12 23:45补: =================开始================= 1.增加quartz :http://www.cnblogs.com/acehalo/p/3902731.h

spring声明式事务管理解析_java

前沿:通过对spring事务管理有了比较深入学习,本文将不做实例,而是指定具体的类和配置文件进行讲解. 本文内容: 1.了解什么是声明式事务? 2.声明式事务管理分别有哪几种? 3.这几种事务管理之间的区别是什么? 一.什么是声明式事务? 声明式事务(declarative transaction management)是spring提供的对程序事务管理的方式之一.Spring的声明式事务就是采用声明的方式来处理事务,用在Spring配置文件中声明式的处理事务来代替代码式的处理事务.这样的好处是

spring声明式事务解析_java

一.spring声明式事务 1.1 spring的事务管理器 spring没有直接管理事务,而是将管理事务的责任委托给JTA或相应的持久性机制所提供的某个特定平台的事务实现.spring容器负责事物的操作,spring容器充当切面,事务的方法称为增强处理,生成的代理对象的方法就是目标方法+增强也就是crud+事务程序员只用做crud的操作,也就是目标方法和声明哪些方法应该在事务中运行. Spring提供了许多内置事务管理器实现: DataSourceTransactionManager:位于or

Spring中的四种声明式事务的配置

Spring中的四种声明式事务的配置Spring容器中有两种思想很重要,也就是我们常用的Ioc和Aop,如果理解了这两种思想,对于我们学习设计模式和编程有很大的帮助,美国四人帮(GOF)写的设计模式中,有很多都用到了Ioc的思想.简单的说就是依赖注入的思想.常见的一种情况:如果一个类中要复用另外一个类中的功能时,我们可能会首先想到继承,如果你知道Ioc这种思想的话,我想你不会用继承,你会马上想到把要用到功能抽取出来,在我们要用到的类中只需通过set方法简单的注入就可以了,其实这里用到了对象的组合

Spring声明式事务管理源码解读之事务提交

在下面的文章中,我讲会多次提到第一篇文章,第一篇文章是:Spring声明式事务管 理源码解读之事务开始 如果要理解事务提交的话,理解事务开始是一个前提条件,所以请先看第一篇文章,再 来看这篇 如果你仔细看下去,我想肯定是有很多收获,因为我们确实能从spring的代码和思想 中学到很多东西. 正文: 其实俺的感觉就是事务提交要比事务开始复杂,看事务是否提交我们还是要回到 TransactionInterceptor类的invoke方法 Java代码 public Object invoke(Met

Spring声明式事务管理源码解读之事务开始

这个是我昨天在解决问题是看源码得一点体验,可能说得比较大概,希望大家多多讨 论,把本贴得质量提高上去,因为spring实现的事务管理这部分我相信还是有点复杂的. 一个人未必能想得十分清楚 在spring的声明式事务管理中,它是如何判定一个及标记一个方法是否应该是处在事 务体之中呢. 首先要理解的是spring是如何来标记一个方法是否应该处在事务体之中的.有这样一 个接口TransactionDefinition,其中定义了很多常量,它还有一个子接口 TransactionAttribute,其中

spring的声明式事务

关于事务配置的详解:Spring事务配置的五种方式 http://www.blogjava.net/robbie/archive/2009/04/05/264003.html 事务的传播特性 在我们用SSH开发项目的时候,我们一般都是将事务设置在Service层那么当我们调用Service层的一个方法的时候它能够保证我们的这个方法中执行的所有的对数据库的更新操作保持在一个事务中,在事务层里面调用的这些方法要么全部成功,要么全部失败.那么事务的传播特性也是从这里说起的.如果你在你的Service层