天天看点

《Spring技术内幕》——3.2节Spring AOP的设计与实现

3.2 spring aop的设计与实现

3.2.1 jvm的动态代理特性

前面已经介绍了横切关注点的一些概念,以及它们在spring中的具体设计和实现。具体来说,在spring aop实现中,使用的核心技术是动态代理,而这种动态代理实际上是jdk的一个特性(在jdk 1.3以上的版本里,实现了动态代理模式)。通过jdk的动态代理特性,可以为任意java对象创建代理对象,对于具体使用来说,这个特性是通过java reflection api来完成的。在了解具体的java reflection之前,先简要地复习一下proxy模式,其静态类图如图3-9所示。

《Spring技术内幕》——3.2节Spring AOP的设计与实现

在图3-9中,可以看到有一个realsubject,这个对象是目标对象,而在代理模式的设计中,会设计一个接口和目标对象一致的代理对象proxy,它们都实现了接口subject的request方法。在这种情况下,对目标对象的request的调用,往往就被代理对象“浑水摸鱼”给拦截了,通过这种拦截,为目标对象的方法操作做了铺垫,所以称之为代理模式。了解了如图3-10所示的调用关系,就可以清楚地了解这里的过程。

在proxy的调用过程中,如果客户(client)调用proxy的request方法,会在调用目标对象的request方法的前后调用一系列的处理,而这一系列的处理相对于目标对象来说是透明的,目标对象对这些处理可以毫不知情,这就是proxy模式。

通过前面的介绍可以知道, jdk中已经实现了这个proxy模式,在基于java虚拟机设计应用程序时,只需要直接使用这个特性就可以了。具体来说,可以在java的reflection包中看到proxy对象,这个对象生成后,所起的作用就类似于proxy模式中的proxy对象。在使用时,还需要为代理对象(proxy)设计一个回调方法,这个回调方法起到的作用是,在其中加入了作为代理需要额外处理的动作,或者说,在这个方法中,所谓额外动作,可以参考proxy模式中的preoperation()和postoperation()方法。这个回调方法,如果在jdk中实现,需要实现下面所示的invocationhandler接口:

在这个接口方法中,只声明了一个invoke方法,这个invoke方法的第一个参数是代理对象实例,第二个参数是method方法对象,代表的是当前proxy被调用的方法,最后一个参数是被调用的方法中的参数。通过这些信息,在invoke方法实现中,已经可以了解proxy对象的调用背景了。至于怎样让invoke方法和proxy挂上钩,熟悉proxy用法的读者都知道,只要在实现通过调用proxy.newintance方法生成具体proxy对象时把invocationhandler设置到参数里面就可以了,剩下的由java虚拟机来完成。

3.2.2 spring aop的设计分析

大家都知道,aop模块是spring的核心模块,虽然在java社区里aspectj是最完整的aop框架,但spring aop也提供了另外一种实现,这种实现并不是aspectj的竞争者,相反,spring aop还将aspectj集成了进来,为ioc容器和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的具体设计和实现。