众所周知,Spring的声明式事务是利用AOP手段实现的,所谓“深入一点,你会更快乐”,本文试图给出相关代码分析。
AOP联盟为增强定义了org.aopalliance.aop.Advice接口,Spring由Advice接口扩展了5中类型的增强(接口),AOP联盟自身提供了IntroductionInterceptor->MethodInterceptor->Interceptor->Advice,而MethodInterceptor就代表环绕增强,表示在目标方法执行前后实施增强。要进行事务操作,正是要在目标方法前后加入相应的代码,因此,Spring为我们提供了TransactionInterceptor类。
TransactionInterceptor的invoke方法调用了父类TransactionAspectSupport的invokeWithinTransactionf方法,
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { // Standard transaction demarcation with getTransaction and commit/rollback calls. TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal = null; try { // This is an around advice: Invoke the next interceptor in the chain. // This will normally result in a target object being invoked. retVal = invocation.proceedWithInvocation(); } catch (Throwable ex) { // target invocation exception completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { cleanupTransactionInfo(txInfo); } commitTransactionAfterReturning(txInfo); return retVal; }
瞬间,我们看到了我们期望看到的代码,其中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默认会自动创建代理。
// AbstractAutowireCapableBeanFactory public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessBeforeInitialization(result, beanName); if (result == null) { return result; } } return result; } public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessAfterInitialization(result, beanName); if (result == null) { return result; } } return result; }
我们来看下AbstractAutoProxyCreator里的重点代码
// AbstractAutoProxyCreator public Object postProcessBeforeInitialization(Object bean, String beanName) { return bean; } /** * Create a proxy with the configured interceptors if the bean is * identified as one to proxy by the subclass. * @see #getAdvicesAndAdvisorsForBean */ public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
/** * Wrap the given bean if necessary, i.e. if it is eligible for being proxied. * @param bean the raw bean instance * @param beanName the name of the bean * @param cacheKey the cache key for metadata access * @return a proxy wrapping the bean, or the raw bean instance as-is */ protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (this.targetSourcedBeans.contains(beanName)) { return bean; } if (this.nonAdvisedBeans.contains(cacheKey)) { return bean; } if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.nonAdvisedBeans.add(cacheKey); return bean; } // Create proxy if we have advice. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { // 有AnnotationAwareAspectJAutoProxyCreator 这个processor时 this.advisedBeans.add(cacheKey); Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } this.nonAdvisedBeans.add(cacheKey); return bean; }
protected Object createProxy( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { ProxyFactory proxyFactory = new ProxyFactory(); // Copy our properties (proxyTargetClass etc) inherited from ProxyConfig. proxyFactory.copyFrom(this); if (!shouldProxyTargetClass(beanClass, beanName)) { // Must allow for introductions; can't just set interfaces to // the target's interfaces only. Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader); for (Class<?> targetInterface : targetInterfaces) { proxyFactory.addInterface(targetInterface); } } Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); for (Advisor advisor : advisors) { proxyFactory.addAdvisor(advisor); } proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(this.proxyClassLoader); }
至于事务切面和其他切面形成切面chain时的调用关系,请参考http://wely.iteye.com/blog/2313924的解释。
本文并未介绍事务属性、事务状态、事务管理器以及事务自身更底层的一些内容,这些内容留待我们研究了mysql的事务后再详细介绍。
相关推荐
NULL 博文链接:https://quicker.iteye.com/blog/674029
用spring AOP(包括几种常用的通知类型)做的小程序
Spring框架-AOP和声明式事务
Spring源代码解析(六):Spring声明式事务处理 Spring源代码解析(七):Spring AOP中对拦截器调用的实现 Spring源代码解析(八):Spring驱动Hibernate的实现 Spring源代码解析(九):Spring Acegi框架鉴权的实现 ...
Spring ax/aop声明式事务配置实例
Spring通过@Transactional注解以及底层的AOP和代理机制实现了声明式事务。这个机制允许开发者通过简单的注解就能控制事务的边界和规则,极大地简化了编程模型。在Spring中,事务管理是通过一系列的拦截器和事务管理...
在Spring3中配置声明式事务比早期版本显得更加简便。只需要几行配置文件+注解就可以实现面向切面的AOP事务
Spring源代码解析(六):Spring声明式事务处理 Spring源代码解析(七):Spring AOP中对拦截器调用的实现 Spring源代码解析(八):Spring驱动Hibernate的实现 Spring源代码解析(九):Spring Acegi框架鉴权的实现 ...
NULL 博文链接:https://tonl.iteye.com/blog/2093314
Spring源代码解析(六):Spring声明式事务处理 7. Spring源代码解析(七):Spring AOP中对拦截器调用的实现 8. Spring源代码解析(八):Spring驱动Hibernate的实现 9.Spring源代码解析(九):Spring Acegi...
Spring源代码解析6:Spring声明式事务处理 .doc Spring源代码解析7:Spring AOP中对拦截器调用的实现 .doc Spring源代码解析8:Spring驱动Hibernate的实现.doc Spring源代码解析9:Spring Acegi框架鉴权的实现.doc ...
1.掌握Myeclipse的使用。 2.掌握spring框架和hibernate框架的使用。 3. 掌握整合spring和hibernate的持久化操作编程 4.掌握基于AOP的声明式事务编程...3.配置WEB-INF/applicationContext.xml提供基于AOP的声明式事务
Spring的声明式事务管理是采用AOP(Aspect-Oriented Programming,面向切面编程)实现的。在编程式事务管理中,各事务处理代码实际上是相似的,这就造成了代码重复;而且编程式事务管理会造成事务管理代码和被管理的...
Spring源代码解析6:Spring声明式事务处理 ; Spring源代码解析7:Spring AOP中对拦截器调用的实现 Spring源代码解析8:Spring驱动Hibernate的实现;Spring源代码解析9:Spring Acegi框架鉴权的实现 Spring源...
<?xml version="1.0" encoding="UTF-8"?><beansxmlns=...aop-2.5.xsd">
Spring提供了声明式事务处理机制,它基于AOP实现,无须编写任何事务管理代码,所有的工作全在配置文件中完成。 二、声明式事务的XML配置方式 为业务方法配置事务切面,需要用到tx和aop两个命名空间下的标签,先在...
Spring源代码解析(六):Spring声明式事务处理.doc Spring源代码解析(七):Spring AOP中对拦截器调用的实现.doc Spring源代码解析(八):Spring驱动Hibernate的实现.doc Spring源代码解析(九):Spring Acegi...
采用声明式事务 1.声明式事务的配置 * 配置sessionFactory * 配置事务管理器 * 配置事务的传播特性 * 配置哪些类哪些方法使用事务 2.编写业务逻辑方法 * 继承HibernateDaoSupport类,使用this....
spring声明式事务的配置 3. spring2.0配置事务 a) 将spring 1.2升级到spring2.0 i. 去掉spring1.2相关的包 ii. 添加spring2.0的jar包:spring.jar,aspecjrt.jar,aspectjweaver.jar 和cglib-nodep-2.1.3,jar iii. ...