zoukankan      html  css  js  c++  java
  • 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的事务后再详细介绍。

    京东技术
  • 相关阅读:
    0909 谈谈我对操作系统的理解
    实验四 主存空间的分配和回收模拟
    12.03进程调度实验点评
    实验三进程调度实验
    实验二 作业调度模拟程序编写
    实验一 DOS命令解释程序的编写
    0909 随笔第一季
    实验四 主存空间的分配和回收模拟
    实验三 进程调度模拟实验
    实验二 作业调度模拟实验
  • 原文地址:https://www.cnblogs.com/wely/p/6198734.html
Copyright © 2011-2022 走看看