Sring AOP的实现机制
动态代理
JDK1.3之后引入了一种称之为动态代理(Dynamic Proxy
)的机制。使用该机制, 我们可以为指定的接口在系统运行期间动态地生成代理对象
,从而帮助我们走出最初使用静态代理实现AOP的窘境。
动态代理机制的实现主要由一个类和一个接口组成,即java.lang.reflect.Proxy
类和java.lang.reflect.InvocationHandler
接口。
下面,让我们看一下,如何使用动态代理来实现之前的“request服务时间控制”功能。虽然要为ISubject
和IRequestable
两种类型提供代理对象,但因为代理对象中要添加的横切逻辑是一样的,所以,我们只需要实现一个InvocationHandler
就可以了,其定义见下方。
然后,我们就可以使用Proxy
类,根据RequestCtrlInvocationHandler
的逻辑,为ISubject
和IRequestable
两种类型生成相应的代理对象实例,见下方代码。
即使还有更多的目标对象类型,只要它们依然织入的横切逻辑相同,用RequestCtrlInvocationHandler
一个类并通过Proxy
为它们生成相应的动态代理实例就可以满足要求。
当Proxy
动态生成的代理对象.上相应的接口方法被调用时,对应的InvocationHandler
就会拦截相应的方法调用,并进行相应处理。InvocationHandler
就是我们实现横切逻辑的地方,它是横切逻辑的载体,作用跟Advice
是一样的。所以,在使用动态代理机制实现AOP的过程中,我们可以在InvocationHandler
的基础上细化程序结构,并根据Advice
的类型,分化出对应不同Advice
类型的程序结构。我们将在稍后看到SpringAOP中的不同Advice
类型实现以及结构规格。
动态代理虽好,但不能满足所有的需求。因为动态代理机制只能对实现了相应Interface
的类使用,如果某个类没有实现任何的Interface
,就无法使用动态代理机制为其生成相应的动态代理对象。对于没有实现任何Interface
的目标对象,我们需要寻找其他方式为其动态的生成代理对象。
默认情况下,如果 SpringAOP 发现目标对象实现了相应 Interface,则采用动态代理机制为其生成代理对象实例。而如果目标对象没有实现任何 Interface
,Spring AOP 会尝试使用一个称为 CGLIB(Code Generation Library)的开源的 动态字节码生成类库,为目标对象生成动态的代理对象实例。
动态字节码生成
使用 动态字节码生成技术扩展对象行为的原理是 ,我们可以对目标对象进行 继承扩展,为其生成相应的子类,而子类可以通过覆写来扩展父类的行为,只要将横切逻辑的实现放到子类中,然后让系统使用扩展后的目标对象的子类,就可以达到与代理模式相同的效果了。
SubClass instanceof SuperClass == true,不是吗?(图8-5演示了一个使用CGLIB进行对象行为扩展的示例。)
但是,使用继承的方式来扩展对象定义,也不能像静态代理模式那样,为每个不同类型的目标对象都单独创建相应的扩展子类。所以,我们要借助于CGLIB这样的动态字节码生成库, 在系统运行期间动态地为目标对象生成相应的扩展子类 。为了演示CGLIB的使用以及最终可以达到的效果,我们定义的目标类如下所示:
CGLIB可以对实现了某种接口的类,或者没有实现任何接口的类进行扩展。但我们已经知道,可以使用 动态代理机制来扩展实现了某种接口的目标类,所以,这里主要演示没有实现任何接口的目标类是如何使用CGLIB来进行扩展的。
要对Requestable
类进行扩展,首先需要实现一个net.sf.cglib.proxy.Callback
。不过更多的时候,我们会直接使用net.sf.cglib.proxy.MethodInterceptor
接口(MethodInterceptor
扩展了Callback
接口)。
下方代码给出了针对我们的Requestable
所提供的Callback
实现。
这样,RequestctrlCallback
就实现了对request()
方法请求进行访问控制的逻辑。现在我们要通过CGLIB的Enhancer
为目标对象动态地生成一个子类,并将RequestCtrlCallback
中的横切逻辑附加到该子类中,代码如下所示:
通过为enhancer指定需要生成的子类对应的父类,以及Callback实现,enhancer最终为我们生成需要的代理对象实例。
使用CGLIB对类进行扩展的唯一限制就是无法对final方法进行覆写。
本章小结
在进入Spring AOP的腹地之前,我们先对Spring AOP的概况进行了介绍。接着,一起探索了Spring AOP的实现机制,包括最原始的代理模式,直至最终的动态代理与动态字节码生成 。
在了解这些内容之后,我们将深入了解Spring AOP的方方面面,先从Spring AOP的最初版本说起…