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

众所周知,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的事务后再详细介绍。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

武汉红喜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值