本章内容

Spring AOP概述、Spring AOP的设计与实现、建立AopProxy代理对象、Spring AOP拦截器调用的实现、Spring AOP的高级特性。

3.1 Spring AOP概述

3.1.1 AOP概念回顾

AOP是Aspect-Oriented Programming(面向方面编程或面向切面)的简称。

关于AOP技术简介:

AspectJ:源代码和字节码级别的编织器,用户需要使用不同于Java的新语言。

AspectWerkz:AOP框架,使用字节码动态编织器和XML配置。

JBoss-AOP:基于拦截器和元数据的AOP框架,运行在JBoss应用服务器上。以及在AOP中用到的一些相关的技术实现:

BCEL(Byte-Code Engineering Library):Java字节码操作类库,具体的信息可以参见项目网站http://jakarta.apache.org/bcel/。

Javassist:Java字节码操作类库,JBoss的一个子项目,项目信息可以参见项目网站http://jboss.org/javassist/。

AOP联盟定义的AOP体系结构如下图所:

最高层是语言和开发环境,“基础”(base)可以视为待增强对象或者说目标对象;“切面”(aspect)通常包含对于基础的增强应用;“配置”(configuration)可以看成是一种编织,通过在AOP体系中提供这个配置环境,可以把基础和切面结合起来,从而完成切面对目标对象的编织实现。

第二个层次面向方面系统,在Spring AOP实现中,使用Java语言来实现增强对象与切面增强应用,并为二者结合提供配置环境。对于编织配置,可以使用IoC容器来完成;对于POJO对象的配置,本来就是Spring的核心IoC容器的强项。AOP体系结构的第二个层次是为语言和开发环境提供支持的,在这个层次中可以看到AOP框架的高层实现,主要包括配置和编织实现两部分内容。

最底层是编织的具体实现模块,图中各种技术都可作为编织逻辑的具体实现方法,比如反射、程序预处理、拦截器框架、类装载器框架、元数据处理等。在Spring AOP中,使用的是Java本身的语言特性,如Java Proxy代理类、拦截器等技术,来完成AOP编织的实现。

3.1.2 Advice通知

Advice(通知)定义在连接点做什么,为切面增强提供织入接口。主要描述Spring AOP围绕方法调用而注入的切面行为。Advice是AOP联盟定义的一个接口,具体的接口定义在org.aopalliance.aop.Advice中。具体的通知类型实现有:BeforeAdvice、AfterAdvice、ThrowsAdvice等。从接口BeforeAdvice开始,首先了解它的类层次关系,如下图:

BeforeAdvice的继承关系中,定义了为待增强的目标方法设置的前置增强接口MethodBeforeAdvice,使用这个前置接口需要实现一个回调函数:  void before(Method method, Object[] args, Object target) throws Throwable;

在Advice的实现体系中,Spring还提供了AfterAdvice这种通知类型,它的类接口关系如图所示:

在图中的AfterAdvice类接口关系中,可以看到一系列对AfterAdvice的实现和接口扩展,如:AfterReturningAdvice就是其中比较常用的一个。以AfterReturningAdvice通知的实现为例,分析一下AfterAdvice通知类型的实现原理。在AfterReturning-Advice接口中定义了接口方法,如下所示: void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable;

在Spring AOP中,还可以看到另外一种Advice通知类型,那就是ThrowsAdvice,它的类层次关系如图所示:

对于ThrowsAdvice,并没有指定需要实现的接口方法,它在抛出异常时被回调,这个回调是AOP使用反射机制来完成的。

3.1.3 Pointcut切点

Pointcut(切点)决定Advice通知应该作用于哪个连接点,也就是说通过Pointcut来定义需要增强的方法的集合,这些集合的选取可以按照一定的规则来完成。在这种情况下,Pointcut通常意味着标识方法,例如,这些需要增强的地方可以由某个正则表达式进行标识,或根据某个方法名进行匹配等。切点在Spring AOP中的类继承体系如图所示:

在Pointcut的基本接口定义中可以看到,需要返回一个MethodMatcher。对于Point的匹配判断功能,具体是由这个返回的MethodMatcher来完成的,也就是说,由这个MethodMatcher来判断是否需要对当前方法调用进行增强,或者是否需要对当前调用方法应用配置好的Advice通知。在Pointcut的类继承关系中,以正则表达式切点 JdkRegexpMethodPointcut的实现原理为例,来具体了解切点Pointcut的工作原理。在JdkRegexpMethodPointcut的基类 StaticMethodMatcherPointcut的实现中可以看到,设置MethodMatcher为StaticMethodMatcher,同时JdkRegexpMethodPointcut也是这个MethodMatcher的子类,它的类层次关系如图:

在Pointcut的类继承关系中,MethodMatcher对象实际上是可以被配置成JdkRegexpMethodPointcut来完成方法的匹配判断的。在JdkRegexpMethodPointcut中,可以看到一个matches方法,这个matches方法是MethodMatcher定义的接口方法。在JdkRegexpMethodPointcut的实现中,这个matches方法就是使用正则表达式来对方法名进行匹配的地方。对matches方法的调用关系如图所示:

在JdkDynamicAopProxy的invoke方法中触发了对matches方法的调用。这里重点了解Pointcut的实现原理,比如matches本身的实现。 JdkRegexpMethodPointcut的matches方法的实现,代码清单如下所示。

在Spring AOP中,还提供了其他的MethodPointcut,比如通过方法名匹配进行Advice匹配的NameMatchMethodPointcut。它的matches方法实现很简单,匹配的条件是方法名相同或者方法名相匹配,如代码清单所示:

3.1.4 Advisor通知器

完成对目标方法的切面增强设计(Advice)和关注点的设计(Pointcut)以后,需要一个对象把它们结合起来,完成这个作用的就是Advisor(通知器)。通过Advisor,可以定义应该使用哪个通知并在哪个关注点使用它。在Spring AOP中,我们以一个Advisor的实现(DefaultPointcutAdvisor)为例,来了解Advisor的工作原理。在DefaultPointcutAdvisor中,有两个属性,分别是advice和pointcut。通过这两个属性,可以分别配置Advice和Pointcut,DefaultPointcutAdvisor的实现如代码清单所示:

在DefaultPointcutAdvisor中,pointcut默认被设置为Pointcut.True,这个Pointcut.True在Pointcut接口中被定义为:Pointcut TRUE = TruePointcut.INSTANCE;    TruePointcut的INSTANCE是一个单件。在TruePointcut的methodMatcher实现中,使用TrueMethodMatcher作为方法匹配器。这个方法匹配器对任何的方法匹配都要求返回true的结果,也就是说对任何方法名的匹配要求,它都会返回匹配成功的结果。和TruePointcut一样,TrueMethodMatcher也是一个单件实现。TruePointcut和TrueMethodMatcher的实现如代码清单所示:

3.2 Spring AOP的设计与实现

3.2.1 JVM的动态代理特性

在Spring AOP实现中,使用的核心技术是动态代理,而这种动态代理实际上是JDK的一个特性(在JDK 1.3以上的版本里,实现了动态代理模式)。通过JDK的动态代理特性,可以为任意Java对象创建代理对象,对于具体使用来说,这个特性是通过Java Reflection API来完成的。

JDK中已经实现了Proxy模式,在基于Java虚拟机设计应用程序时,只需要直接使用这个特性就可以了。具体来说,可以在Java的reflection包中看到Proxy对象,这个对象生成后,所起的作用就类似于Proxy模式中的Proxy对象。在使用时,还需要为代理对象(Proxy)设计一个回调方法,这个回调方法起到的作用是,在其中加入了作为代理需要额外处理的动作。在JDK中实现,需要实现下面所示的InvocationHandler接口:

invoke方法的第一个参数是代理对象实例,第二个参数是Method方法对象,代表的是当前Proxy被调用的方法,最后一个参数是被调用的方法中的参数。至于怎样让invoke方法和Proxy挂上钩,熟悉Proxy用法的读者都知道,只要在实现通过调用Proxy.newIntance方法生成具体Proxy对象时把InvocationHandler设置到参数里面就可以了,剩下的由Java虚拟机来完成。

3.2.2 Spring AOP的设计分析

Spring AOP的核心技术是JDK动态代理技术。以动态代理技术为基础,设计出了一系列AOP的横切实现,比如前置通知、返回通知、异常通知等。同时,Spring AOP还提供了一系列的Pointcut来匹配切入点,可以使用现有的切入点来设计横切面,也可以扩展相关的Pointcut方法来实现切入需求。

在Spring AOP中,虽然对于AOP的使用者来说,只需要配置相关的Bean定义即可,但仔细分析Spring AOP的内部设计可以看到,为了让AOP起作用,需要完成一系列过程,比如,需要为目标对象建立代理对象,这个代理对象可以通过使用JDK的Proxy来完成,也可以通过第三方的类生成器cglib来完成。然后,还需要启动代理对象的拦截器来完成各种横切面的织入,这一系列的织入设计是通过一系列Adapter来实现的。通过一系列Adapter的设计,可以把AOP的横切面设计和Proxy模式有机地结合起来,从而实现在AOP中定义好的各种织入方式。

3.2.3 Spring AOP的应用场景

Spring AOP为IoC的使用提供了更多的便利,一方面,应用可以直接使用AOP的功能,设计应用的横切关注点,把跨越应用程序多个模块的功能抽象出来,并通过简单的AOP的使用,灵活地编制到模块中,比如可以通过AOP实现应用程序中的日志功能。另一方面,在Spring内部,一些支持模块也是通过Spring AOP来实现的,比如后面将要详细介绍的事务处理。从这两个角度就已经可以看到Spring AOP的核心地位了。下面以ProxyFactoryBean的实现为例,和大家一起来了解Spring AOP的具体设计和实现。

3.3 建立AopProxy代理对象

3.3.1 设计原理

在Spring的AOP中,一个主要的部分是代理对象的生成,而对于Spring应用,是通过配置和调用Spring的ProxyFactoryBean来完成这个任务。在ProxyFactoryBean中,封装了主要代理对象的生成过程。在这个过程中,可以使用JDK的ProxyCGLIB两种生成方式。

以ProxyFactory的设计为中心,可以看到相关的类继承关系如图所示:

在这个类继承关系中,可以看到完成AOP应用的类,比如AspectPxoxyFactory、ProxyFactory和ProxyFactoryBean,都在同一个类的继承体系下,都是ProxyConfig、AdvicedSupport 和ProxyCreatorSupport的子类。作为共同基类ProxyConfig为ProxyFactoryBean这样的子类提供了配置属性;在另一个基类AdvisedSupport的实现中,封装了AOP对通知后台通知器的相关操作,这些操作对于不同的AOP的代理对象的生成都是一样的,但对于具体的AOP代理对象的创建,AdvisedSupport把它交给它的子类们去完成;对于ProxyCreatorSupport,可以将它看成是其子类创建AOP代理对象的一个辅助类。通过继承以上提到的基类的功能实现,具体的AOP代理对象的生成,根据不同的需要,分别由ProxyFactoryBean、AspectJProxyFactory后台ProxyFactory来完成。对于需要使用AspectJ的AOP应用,AspectJProxyFactory起到集成Spring和AspectJ的作用;对于使用Spring AOP的应用,ProxyFactoryBean(可在IoC容器中完成声明式配置)和ProxyFactory(需要编程式使用SpringAOP)都提供了AOP功能的封装。

3.3.2 配置ProxyFactoryBean

以ProxyFactoryBean为例,分析Spring AOP的实现原理,ProxyFactoryBean是在SpringIoC环境中创建AOP应用的底层方法,是一个非常灵活的创建AOP应用的底层方法,Spring通过它完成了对AOP使用的封装。

3.3.3 ProxyFactoryBean生成AopProxy代理对象

从ProxyFactoryBean的简单配置例子可看出,ProxyFactoryBean是用来配置目标对象和切面行为Advice的,ProxyFactoryBean通过其配置的拦截器名称interceptorNames即通知器Advisor将切面行为Advice应用到目标对象中。

在ProxyFactoryBean中,需要为待增强目标对象目标对象生成Proxy代理对象,从而为AOP切面的编织提供基础,AOP Proxy的生成有两种方式,依赖JDK或者CGLIB提供的Proxy特性,代理生成过程如下图:

initializeAdvisorChain():初始化通知器链,通知器链中封装了一系列从配置中读取的拦截器,为代理对象的生成做好准备。

getSingletonInstance():生成Singleton类型的Proxy 。

DefaultAopProxyFactory :AopProxy接口类,AopProxy有两个子类实现,一个是JdkDynamicAopProxy,一个是CglibProxyFactory 。

从FactoryBean中获取对象是以getObject方法作为入口完成的,ProxyFactoryBean实现中的getObject()方法,是FactoryBean需要实现的接口。对ProxyFactoryBean来说,需要对目标对象增加的增强处理,都通过了getObject方法进行了封装,这些增强处理是为AOP功能的实现提供服务的。getObject的实现清单如下。getObect()方法首先对通知器进行了初始化,通知器封装了一系列的拦截器,这些拦截器都要从配置文件中获取,然后为代理对象的生成做好准备。在生成代理对象时,因为Spring中有singleton类型和prototype类型这两种不同的bean,所有要对代理对象进行一个区分。

为Proxy代理对象配置Advisor链是在initializeAdvisorChain方法中实现的。这个初始化过程中有一个标志位AdvisorChainInitialized,这个标志用来表示通知器是否已经初始化。如果已经初始化,那么这里就会在初始化,而是直接返回。也就说,这个初始化的工作发生在应用第一次通过ProxyFactoryBean去获取代理对象的时候。在完成这个初始化之后,接着读取配置中出现的所有通知器,这个取得通知器的过程也比较简单,把通知器的名字交给容器的getBean方法就可以了,这是通过对IOC容器实现的一个回调完成的。然后把从IOC容器中取得的通知器加入到拦截器链中,这个动作是由addAdvisorOnChainCreation方法来实现的。

接着在getObject()方法中,将会执行getSingletonInstance()方法,该方法主要是生成代理对象并封装对target目标对象的调用(即加入拦截器)。具体的生成过程是,首先读取ProxyFactoryBean中的配置,为生成代理对象做好必要的准备,比如设置代理的方法接口调用等。Spring通过AopProxy类来具体生成代理对象。对于getSingletonInstance()方法中代理对象的生成过程,代码清单如下:

这里出现了AopProxy对象类型,Spring利用AopProxy接口类把AOP代理对象的实现与框架其他部分有效隔离开来。AopProxy接口有两个子类实现,一个Cglib2AopProxy,另一个是JdkDynamicProxy。 具体代理对象的生成是在ProxyFactoryBean的基类AdvisedSupport中实现,借助AopProxyFactory完成,这个对象要么从JDK中生成,要么借助CGLIB获得。下面看看ProxyCreatorSupport中是如何生成代理对象的。

AopProxy代理对象的生成有两种方式,如果目标对象是接口类使用JDK来生成,否则Spring会使用CGLIB来生成目标的代理对象。下面看看在DefaultAopProxyFactory是如何生成AopProxy目标代理对象的:

在AopProxy代理对象的生成过程中,首先要从AdviseSupport对象中取得配置的目标对象,AOP完成的是切面应用对目标应用对象的增强。如果这里没有配置目标对象会直接抛出异常。一般而言,默认方式是使用JDK来产生AopProxy代理对象,但如果配置的目标对象不是接口类的实现,会使用CGLIB来产生AopProxy代理对象;在使用CGLIB来产生AopProxy代理对象时,因为CGLIB是第三方类库,本身不在JDK基类库中,所有需要在classPath中正确配置,以便能够加载和利用。在Spring中,使用JDK和CGLIB来生成AopProxy代理对象的工作,是由JdkDynamicAopProxy和CglibProxyFactory来完成。

3.3.4 JDK生成AopProxy代理对象

通过上面我们已经知道生成AopProxy对象有两种方式,下面看下类图:

JdkDynamicAopProxy生成代理对象:

newProxyInstance方法:需要指明3个参数,类装载器,代理接口,Proxy回调方法所在的对象,这个对象要实现InvocationHandler接口 .InvocationHandler接口: 反射类接口,定义了invoke方法,提供代理对象的回调入口。

3.3.5 CGLIB生成AopProxy代理对象

配置Enhancer对象,通过Enhancer对象的callback回调设置生成代理对象。其中通过设置DynamicAdvisedInterceptor拦截器来完成AOP功能的。

3.4 Spring AOP拦截器调用的实现

3.4.1 设计原理

在Spring AOP通过JDK的Proxy方式或CGLIB方式生成代理对象的时候,相关的拦截器已经配置到代理对象中去了,拦截器在代理对象中起作用是通过对这些方法的回调来完成的。 如果使用JDK的Proxy来生成代理对象,那么需要InvocationHandler来设置拦截器回调,而如果使用CGLIB来生成代理对象,通过DynamicAdvisedInterceptor来完成回调。

3.4.2 JdkDynamicAopProxy的invoke拦截

在JDKDynamicAopProxy生成代理对象时,它的AopProxy代理对象生成调用:

Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);

this指的是InvocationHandler对象,InvocationHandler是JDK定义反射类的一个接口,这个接口定义了invoke方法,此方法为回调方法。通过invoke的具体实现,来完成对目标对象方法调用的拦截器或者功能增强工作。在这个方法中,包含一个完整的拦截器链对目标对象的拦截过程,比如获取拦截器链中的拦截器进行配置,逐个运行拦截器链里的拦截器增强,知道最后的目标对象方法的运行。下面看下invoke的源码:

3.4.3 CglibAopProxy的intercept拦截器

CglibAopProxy实现DynamicAdcisedIntercepte接口,该接口有intercept()方法。

3.3.4 目标方法的调用

如果没有拦截器会对目标对象方法直接调用。对于JDKDynamicAopProxy代理对象是通过AopUtils使用反射机制实现的。在这个调用方法中首先得到调用方法的反射对象,然后使用invoke启动对方法反射对象的调用。源码如下:

对于使用Cglib2AopProxy的代理对象,其目标对象的调用是通过CGLIB的MethodProxy对象直接完成。retVal=methodProxy.invoke(target,args);

3.4.5 AOP拦截器的调用

下面进入AOP的核心部分,Aop是怎样完成对目标的增强的。这些都封装在Aop拦截器链中,由一个个具体的拦截器完成。 无论是使用JDKDynamicAopProxy还是使用CglibAopProxy创建代理对象最终对AOP拦截链的调用都是在ReflectiveMethodInvocation中通过proceed方法实现的。在proceed方法中逐个运行拦截器的拦截方法。在运行拦截器的拦截方法之前需要对代理方法完成一个匹配,通过这个匹配判断来决定拦截器是否满足切面增强的要求。具体代码如下:

3.4.6 配置通知器

在整个AopProxy代理对象拦截回调过程中,先回到ReflectionMethodInvocation类的proceed方法,在这个方法里,可以看到得到了配置的interceptorOrInterceptionAdvice,如下所示:

Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);

interceptorOrInterceptionAdvice是获得的拦截器,它通过拦截器机制对目标对象进行增强。这个拦截器来自interceptorsAndDynamicMethodMatchers。具体来说,他是interceptorsAndDynamicMathers持有的List中的一个元素。关于如何配置拦截器的问题就转化为了List中的拦截器元素是从哪里来的,在哪里配置的问题。接着对invoke调用进行回放,回到JDKDynamicAopProxy中的invoke方法中,可以看到这个List中的interceptors是从哪个调用中获取的。对于CglibAopProxy,也有类似过程,只不过这个过程是在DynamicAdvisedInterceptor的intercept回调中实现的,如下所示:

List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method,targetClass);

从上面的代码可以看出,获取intercptors的操作是由advised对象完成的,这个advised是一个AdvisedSupport对象,从AdvisedSupport类中可以看到getInterceptorsAndDynamicInterceptionAdvice的实现。在这个方法中取得了拦截器链,再取得拦截器链的时候,为了提高拦截器链的效率,还为这个拦截器链这是了缓存。

获取拦截器的工作由配置好的advisorChainFactory来完成,advisorChainFactory被配置成DefaultAdvisorChainFactory,在 DefaultAdvisorChainFactory中实现了interceptor链的获取过程,在这个过程中,首先设置了一个List,其长度是配置的通知器的个数来决定的,这个配置时在XML中对ProxyFactoryBean做的interceptNames属性的配置,然后,DefaultAdvisorChainFactory会通过一个AdvisorAdapterRegistry来实现拦截器的注册。AdvisorAdapterRegistry对advice通知的织入功能起了很大作用。有了AdvisorAdapterRegistry注册器,利用他来对ProxyFactoryBean配置中得到的通知进行适配,从而得到相应的拦截器,再把他前面设置好的List中去,完成所谓的拦截器注册过程。在拦截器适配和注册过程完成以后,List中的拦截器会被JDK生成的AopProxy代理对象的invoke方法或者CGLIB代理对象的intercept拦截方法获得,并启动拦截器的invoke方法调用,最终触发通知的切面增强。

下面看看DefaultAdvisorChainFactory是怎样生成拦截器链的:

在ProxyFactoryBean的getObject方法中对adviosr进行初始化,从XML配置中获取了advisor通知器。下面看下在ProxyFactoryBean拦截器链的初始化中获取advisor通知器

advisor通知器的取得时委托给IOC容器完成的,但是在ProxyFactoryBean中是如何获得IOC容器,然后通过回调IOC容器的getBean方法来得到需要的通知advisor?在这里大家可以回顾下IOC容器的原理。

3.4.7 Advice通知的实现

AopProxy代理对象生成时,其拦截器也一并生成。下面我们来分析下Aop是如何对目标对象进行增强的。在为AopProxy配置拦截器的实现中,有一个取得拦截器配置过程,这个过程由DefaultAvisorChainFactory实现的,而这个工厂类负责生成拦截器链,在它的getInterceptorsAndDynamicInterceptionAdvice方法中,有一个适配器的注册过程,通过配置Spring预先设计好的拦截器,Spring加入了它对Aop实现的处理。为详细了解这个过程,先从DefaultAdvisorChainFactory的实现开始,通过以下代码可以看到,在DefaultAdvisorChainFactory实现中,首先构造了一个GlobalAdvisorAdapterRegistry单件,然后对配置的Advisor通知器进行逐个遍历,这些通知链都是配置在interceptorNames中的,从getInterceptorsAndDynamicInterceptionAdvice传递进来的advised参数对象中,可以方便的取得配置的通知器,有了这些通知器,接着就是一个由 GlobalAdvisorAdapterRegistry来完成的拦截器的适配和注册。

GlobalAdvisorAdapterRegistry的getInterceptors方法为AOP的实现做出了很大的贡献,这个方法封装着advice织入实现的入口,我们先从GlobalAdvisorAdapterRegistry的实现入手,他基本起一个适配器的作用,但同时也是单件模式,代码如下:

到这里,我们知道在DefaultAdvisorAdapterRegistry中,设置了一系列的adapter适配器,这是这些适配器的实现,为Spring的advice提供了编织能力,下面我们看看DefaultAdvisorAdapterRegistry究竟发生了什么?adapter的作用具体分为两个:

1、调用adapter的support方法,通过这个方法来判断取得的advice属于什么类型的advice通知,从而根据不同的advice类型来注册不同的AdviceInterceptor,也就是前面我们看到的拦截器

2、这些AdviceInterceptor都是Spring AOP框架设计好的,是为实现不同的advice功能提供服务的。有了这些AdviceInterceptor,可以方便的使用由Spring提供的各种不同的advice来设计AOP应用。也就是说,正是这些AdviceInterceptor最终实现了advice通知在AopProxy对象中的织入功能。

剥茧抽丝,继续看adapter,在DefaultAdvisorRegistry的getInterceptors调用中,从MethodBeforeAdviceAdapter、AfterReturningAdviceAdapter、ThrowsAdviceAdaper这几个通知适配器的名字上可以看出和Advice一一对应,在这里,他们作为适配器被加入到adapter的List中,他们都是实现AdvisorAdapter接口的同一层次的类,只是各自承担着不同的适配的任务,一对一的服务于不同的advice实现。以MethodBeforeAdviceAdapter为例,代码如下:

到这里就非常清楚了,Spring AOP为了实现advice的织入,设计了特定拦截器对这些功能进行了封装。虽然应用不会直接用到这些拦截器,但却是advice发挥作用不可缺少的准备。还是以MethodBeforeAdviceInterceptor为例,我们看看advice是如何封装的。在invoke回调方法中,看到首先触发了advice的before的回调,然后才是MethodInvocation的proceed方法的调用。看到这里,就已经和前面的在ReflectionMethodInvocation的Proceed分析中联系起来。回忆了一下,在AopProxy代理对象触发的ReflectionMethodInvocation的proceed方法中,在取得拦截器以后,启动了对拦截器invoke方法的调用。按照AOP的规则,ReflectiveMethodInvocation触发的拦截器invoke方法,最终会根据不同的advice类型,触发Spring对不同的advice的拦截器封装,比如对MethodBeforeAdvice,最终会根据不同的advice类型触发Spring对不同的advice的拦截器封装。比如对MethodBeforeAdvice,最终会触发MethodBeforeAdviceInterceptor的invoke方法。在MethodBeforeAdviceInterceptor方法中,会调用advice的before方法,这就是MethodBeforeAdvice所需要的对目标对象的增强效果:在方法调用之前通知增强。

完成MethodBeforeAdviceInterceptor的调用,然后启动advice通知的afterReturning回调,代码如下:

ThrowsAdvice的实现和上面类似,也是封装在对应的AdviceInterceptor中,ThrowsAdvice的回调方法要复杂一些,他维护了一个exceptionHandlerMap来对应不同的方法调用场景,这个exceptionHandlerMap中的handler的取得时与触发ThrowsAdvice增强的异常相关的。

3.4.8 ProxyFactory实现AOP

除了使用ProxyFactory Bean实现AOP之外,还可以使用ProxyFactory 编程式的完成AOP应用的设置。下面举一个使用ProxyFactory的例子:

TargetImpl  target =new TargetImpl();ProxyFactory aopFactory =new ProxyFactory(target);aopFactory.addAdvisor(yourAdvisor);aopFactory.addAdvice(yourAdvice);TargetImpl targetProxy =(TargetImpl  )new aopFactory.getProxy();public class  ProxyFactory   extends   ProxyCreatorSupport{public Object getProxy() {return createAopProxy().getProxy();}}

Spring技术内幕(3)Spring AOP的实现相关推荐

  1. 《Spring技术内幕(第2版)》PDF 国内经典分析spring源代码

    书名:Spring技术内幕(第2版) 作者: 计文柯 出版社: 机械工业出版社 副标题: 深入解析Spring架构与设计原理 出版年: 2012-2 页数: 399 定价: 69.00元 装帧: 平装 ...

  2. 资深架构师推荐Spring技术内幕:深入了解Spring的底层机制

    程序员都很崇拜技术大神,很大一部分是因为他们发现和解决问题的能力,特别是线上出现紧急问题时,总是能够快速定位和解决. 一方面,他们有深厚的技术基础,对应用的技术知其所以然,另一方面,在采坑的过程中不断 ...

  3. Spring技术内幕

    Spring技术内幕--深入解析Spring架构与设计原理 图 书 内 容 本书是Spring领域的问鼎之作,由业界拥有10余年开发经验的资深Java专家亲自执笔!Java开发者社区和Spring开发 ...

  4. Spring技术内幕:设计理念和整体架构概述

    为什么80%的码农都做不了架构师?>>>    程序员都很崇拜技术大神,很大一部分是因为他们发现和解决问题的能力,特别是线上出现紧急问题时,总是能够快速定位和解决. 一方面,他们有深 ...

  5. Spring技术内幕总结

    最近一段时间看了一下书名叫<Spring技术内幕--深入解析Spring架构与设计原理>,这么熟将spring写的非常的经典,将spring所有的内幕技术解析的非常的详细,自己只是粗略的大 ...

  6. 华章揭秘系列精品图书(《Android应用开发揭秘》、《GWT揭秘》、《Spring技术内幕》)...

    Android应用开发揭秘(国内首本基于Andriod 2.0的经典著作,5大专业社区一致鼎力推荐!互动网畅销排行榜第1名) 作者:杨丰盛 出版社:机械工业出版社 标准书号:978-7-111-291 ...

  7. Spring 技术内幕读书笔记

    Spring的设计理念和整体架构 1.1 spring的各个子项目 1.1.1 spring framwork 核心, IoC容器设计,控制反转,AOP ,MVC ,JDBC ,事务处理 1.1.2 ...

  8. 《Spring技术内幕》——1.4节Spring的应用场景

    1.4 Spring的应用场景 通过介绍Spring架构设计,我们了解到Spring是一个轻量级的框架.在Spring这个一站式的应用平台或框架中,其中的各个模块除了依赖IoC容器和AOP之外,相互之 ...

  9. spring技术内幕——深入解析spring架构与设计原理

    林纳斯·托瓦兹(Linus Torvalds)说:"我从心底认为,优秀的程序员与平庸的程序员之间的区别,是在于认为自己的代码重要还是数据结构更加重要.平庸的程序员眼里只有代码,优秀的程序员则 ...

最新文章

  1. 34补1-2_3 HA Cluster基础及heartbeat实现HA
  2. <笔记1>matplotlib绘图工具笔记
  3. 服!AI 让兵马俑“活”起来,颜值惊艳!
  4. 搜索引擎爬虫蜘蛛的USERAGENT大全
  5. 解决oh my zsh Insecure completion-dependent directories detected
  6. C++实现插入排序(附完整源码)
  7. 如何查看 ToggleStatusComponent 是否是 SAP Spartacus public API 一部分
  8. limesurvey php5.2,limesurvey(配置心得)
  9. python小测试1答案_测试1:Python 基本语法(选择题
  10. 【SpringCloud】Ribbon 负载均衡
  11. 在硅晶片上实现量子计算,英特尔可能改变了这项技术的未来
  12. 卡爆mysql_荐 MySQL死锁和卡死分析
  13. Echarts柱状图配置
  14. Oracle执行计划变更
  15. 迅雷离线下载节点分布
  16. 使用vs2019用c++创建dll库
  17. 【JAVA】 容纳对象 Set
  18. bootstrap 上传图片插件 file-input 的简单使用
  19. cloudreve旧版php下载,cloudreve
  20. html动画箭头,纯css动画实现箭头向右无限前进

热门文章

  1. C语言怎么输入float的变量,c语言float怎么用
  2. 什么是网络渠道营销根本?(二)
  3. unity发布WebGl,Win10搭建IIS服务器,开启本地IIS服务,
  4. Windows设置本地DNS域名解析Hosts
  5. 100天精通Python(可视化篇)——第84天:matplotlib绘制不同种类炫酷直方图参数说明+代码实战(普通、多变量、堆叠、分组、多个子图、折线、曲线直方图)
  6. TCP四次挥手会经历这么多状态
  7. ai前世识别_ai人脸扫描前世身份
  8. Java傲视其他语言的优势及其特点
  9. 位于磁盘不同磁道的扇区读写速度是否一样
  10. 【原创】软件架构技术发展历程总结及思考 1of2(待续)