
3.6 小结
在Spring的平台功能中,AOP是一个核心模块,通过对AOP的使用,极大地丰富了Spring框架的功能,比如在各种驱动组件的实现上,很灵活地运用了AOP的功能特性。关于这一点,在本书接下来的几章中,读者可以很充分地了解。对于Spring应用,可以直接使用Spring AOP的功能,有了这些功能,对应用的模块化设计有很大的作用;同时,AOP技术的使用,也丰富了应用在设计上的技术选择。
本章对最基本的Spring AOP的实现方式进行了解析,具体来说,以ProxyFactory-Bean和ProxyFactory的实现为例,对Spring AOP的基本实现和工作原理进行了一些梳理和分析。ProxyFactoryBean是在IoC环境中创建代理的一个很灵活的方法,与其他方法相比,虽然有些繁琐,但并不妨碍大家从ProxyFactoryBean入手,去了解AOP在Spring中的基本实现。
在Spring AOP的基本实现中,可以了解Spring如何得到AopProxy代理对象,以及如何利用AopProxy代理对象来对拦截器进行处理。Proxy代理对象的使用,在Spring AOP的实现过程中是非常重要的一个部分,Spring AOP充分利用了像Java的Proxy、反射技术以及第三方字节码技术实现CGLIB这些技术方案,通过这些技术,完成了AOP需要的AopProxy代理对象的生成。回顾通过ProxyFactoryBean实现AOP的整个过程,可以看到,在它的实现中,首先需要对目标对象以及拦截器进行正确配置,以便AopProxy代理对象顺利产生;这些配置既可以通过配置ProxyFactoryBean的属性来完成,也可以通过编程式地使用ProxyFactory来实现。这两种AOP的使用方式只是在表面配置的方式上不同,对于内在的AOP实现原理它们是一样的。在生成AopProxy代理对象的时候,Spring AOP设计了专门的AopProxyFactory作为AopProxy代理对象的生产工厂,由它来负责产生相应的AopProxy代理对象,在使用ProxyFactoryBean得到AopProxy代理对象的时候,默认使用的AopProxy代理对象的生产工厂是DefaultAopProxyFactory对象。这个对象是AopProxy生产过程中一个比较重要的类,它定义了AopProxy代理对象的生成策略,从而决定使用哪种AopProxy代理对象的生成技术(是使用JDK的Proxy类还是使用CGLIB)来完成生产任务。而最终的AopProxy代理对象的产生,则是交给JdkDynamicAopProxy和Cglib2AopProxy这两个具体的工厂来完成,它们使用了不同的生产技术,前者使用的是JDK的Proxy技术(它使用InvocationHandler对象的invoke完成回调),后者使用的是CGLIB的技术。
在得到AopProxy代理对象后,在代理的接口方法被调用执行的时候,也就是当AopProxy暴露代理的方法被调用的时候,前面定义的Proxy机制就起作用了。当Proxy对象暴露的方法被调用时,并不是直接运行目标对象的调用方法,而是根据Proxy的定义,改变原有的目标对象方法调用的运行轨迹。这种改变体现在,首先会触发对这些方法调用进行拦截,这些拦截为对目标调用的功能增强提供了工作空间。拦截过程在JDK的Proxy代理对象中,是通过invoke方法来完成的,这个invoke方法是虚拟机触发的一个回调;而在CGLIB的Proxy代理对象中,拦截是由设置好的回调callback方法来完成的。有了这些拦截器的拦截作用,才会有AOP切面增强大显身手的舞台。
具体来说,在ProxyFactoryBean的回调中,首先会根据配置来对拦截器是否与当前的调用方法相匹配进行判断。如果当前的调用方法与配置的拦截器相匹配,那么相应的拦截器就会开始发挥作用。这个过程是一个遍历的过程,它会遍历在Proxy代理对象中设置的拦截器链中的所有拦截器。经过这个过程后,在代理对象中定义好的拦截器链中的拦截器会被逐一调用,直到整个拦截器的调用完成为止。在对拦截器的调用完成以后,才是对目标对象(target)的方法调用。这样,一个普通的Java对象的功能就得到了增强,这种增强和现有的目标对象的设计是正交解耦的,这也是AOP需要达到的一个目标。
在拦截器的调用过程中,实际上已经封装了Spring对AOP的实现,比如对各种通知器的增强织入功能。尽管在使用Spring AOP的时候,看到的是一些advice的使用,但实际上这些AOP应用中接触到的advice通知是不能直接对目标对象完成增强的。为了完成AOP应用需要的对目标对象的增强,Spring AOP做了许多工作,对应于每种advice通知,Spring设计了对应的AdviceAdapter通知适配器,这些通知适配器实现了advice通知对目标对象的不同增强方式。对于这些AdviceAdapter通知适配器,在AopProxy代理对象的回调方法中,需要有一个注册机制,它们才能发挥作用。完成这个注册过程之后,在拦截器链中运行的拦截器已经是经过这些AdviceAdapter适配过的拦截器了。有了这些拦截器,再去结合AopProxy代理对象的拦截回调机制,才能够让advice通知对目标对象的增强作用实实在在地发生。“谁知盘中餐,粒粒皆辛苦”,在软件开发世界里,没有什么免费午餐,看起来简洁易用的AOP,和IoC容器的实现一样,背后同样蕴含着许多艰苦的努力。
除了提供AOP的一些基本功能之外,Spring还提供了许多其他高级特性让用户更加方便地使用AOP。对于这些高级特性,本章选取了HotSwappableTargetSource来对它的实现原理进行分析,一叶知秋,希望能够在这里为对AOP其他特性的实现感兴趣的读者打开一扇门。
本章还提到了Proxy、反射等Java虚拟机特性的使用,CGLIB的使用,以及在它们建立的Proxy对象的基础上对拦截器特性的灵活运用,这些特性都是掌握本章内容的背景知识和重要基础。同时,不妨反过来看,通过了解本章中AOP的实现原理,也为使用这些Java虚拟机的特性以及CGLIB的技术提供了生动而精彩的应用案例。在AOP的实现中,还有一个值得注意的地方,ProxyFactoryBean得到Advisor配置的实现过程,是通过回调IoC容器的getBean方法来完成的,这个处理既简洁又巧妙,是灵活使用IoC容器功能的一个非常好的实例。以上这些,都是在本章中除了Spring AOP实现原理本身之外,非常值得读者学习和研究的地方。
Spring AOP秉持Spring的一贯设计理念,致力于AOP框架与IoC容器的紧密集成,通过集成AOP技术为Java EE应用开发中遇到的普遍问题提供解决方案,从而为AOP用户使用AOP技术提供最大的便利,为Java EE的应用开发人员服务。鉴于此,本章很大一部分内容与AOP和IoC容器的集成有比较大的关系。在没有使用第三方AOP解决方案的时候,Spring通过虚拟机的Proxy特性和CGLIB实现了AOP的基本功能,毫无疑问,这是本章阐述的主要内容和基本线索。有了Spring AOP实现原理的知识背景,为我们了解其他AOP框架与IoC容器的集成原理打下了很好的基础。如果读者感兴趣,可以了解一下优秀的AOP解决方案AspectJ和AspectWerkz是怎样与IoC容器集成的。