Spring AOP怎么实现接口拦截?以Spring 3的ProxyFactoryBean为例

网安智编 厦门萤点网络科技 2025-12-12 00:10 58 0
3.6  AOP的实现原理 AOP的实现是通过创建目标对象的代理类,并对目标对象进行拦截来实现的。分析 AOP的底层实现,需要重点分析几个常用类,相关类图如3-15所示。 类是一个基类——数据类,主要为各种AOP代理工厂提供属性配置。 类...

3.6  AOP的实现原理

AOP的实现是通过创建目标对象的代理类,并对目标对象进行拦截来实现的。分析 AOP的底层实现,需要重点分析几个常用类,相关类图如3-15所示。

类是一个基类——数据类,主要为各种AOP代理工厂提供属性配置。

类是类的子类,其封装了AOP中对通知()和通知器()的相关操作,这些操作对于不同的创建代理对象的类都是相同的,但是对于具体的AOP代理对象的生成需要各个子类去实现。

Spring AOP实现原理_ProxyConfig类分析_spring3 aop 接口拦截

图3-15  AOP核心类图

类是的子类——辅助类,不同子类的一些通用的操作都封装在中。

,和是用于创建AOP代理对象的,这三个类的作用分别如下:

• 类:功能是创建声明式的代理对象。

• 类:功能是创建编程式的代理对象。

• 类:功能是创建基于的代理对象。

3.6.1 设计原理

下面以为例,分析 AOP的实现原理。

首先定义一个接口Log,其中包含一个()方法,Log接口的代码如下:

spring3 aop 接口拦截_ProxyConfig类分析_Spring AOP实现原理

再创建一个类,实现Log接口,重写方法,类的代码如下:

ProxyConfig类分析_spring3 aop 接口拦截_Spring AOP实现原理

然后创建一个通知类并实现接口,重写()方法,在方法执行前后分别打印实现,的实现如下:

ProxyConfig类分析_Spring AOP实现原理_spring3 aop 接口拦截

创建一个测试类,用于观察测试结果,测试代码如下:

spring3 aop 接口拦截_Spring AOP实现原理_ProxyConfig类分析

文件--.xml的配置如下:

spring3 aop 接口拦截_Spring AOP实现原理_ProxyConfig类分析

运行测试代码,测试结果如下:

     方法执行开始时间:2018-10-03 08:18:51 167
     执行一些操作
     方法执行结束时间:2018-10-03 08:18:52 172

从测试结果可以看出,在正常的调用()方法前后分别打印了日志,说明AOP已经实现了。下面将通过这个案例分析的实现逻辑。

打开的代码,其生成代理对象的核心方法是()方法,部分代码如下:

ProxyConfig类分析_Spring AOP实现原理_spring3 aop 接口拦截

下面分析()方法中的in()方法,in()方法是初始化通知器链(或者叫拦截器链)的,其代码如下:

ProxyConfig类分析_Spring AOP实现原理_spring3 aop 接口拦截

执行in()方法后,如果是单例模式,将会调用()方法获取一个单例模式的代理对象,()方法代码如下:

ProxyConfig类分析_Spring AOP实现原理_spring3 aop 接口拦截

执行in()方法后,如果是非单例模式即原型模式,将会调用()方法获取一个新的原型模式的代理对象,()方法代码如下:

spring3 aop 接口拦截_Spring AOP实现原理_ProxyConfig类分析

可以发现,无论是单例模式还是原型模式,最终都是通过调用()方法获取代理对象的,()的实现如下:

ProxyConfig类分析_Spring AOP实现原理_spring3 aop 接口拦截

spring3 aop 接口拦截_ProxyConfig类分析_Spring AOP实现原理

通过以上对()方法和()方法的代码注释可以发现,这两个方法都会调用.()方法,类的核心代码如下:

Spring AOP实现原理_spring3 aop 接口拦截_ProxyConfig类分析

从()方法的代码可以看出,对象是在ry类的()方法中生成的,ry.()方法的代码如下:

ProxyConfig类分析_spring3 aop 接口拦截_Spring AOP实现原理

从ry.()使用的类的名称可以发现,如果是继承了接口的类,会使用JDK动态代理,即用类创建代理对象,否则将会使用CGLIB动态代理即用xy类创建代理对象,关于这两种动态代理的具体使用,请参考本章3.1节。

3.6.2 

JDK动态代理只能针对接口起作用,中通过类使用JDK动态代理创建对象,类的定义如下:

Spring AOP实现原理_ProxyConfig类分析_spring3 aop 接口拦截

类实现了接口,因而可以使用JDK动态代理产生代理对象。

ProxyConfig类分析_spring3 aop 接口拦截_Spring AOP实现原理

此处的()方法是获取代理对象的入口,其是通过调用以下方法实现的:

Spring AOP实现原理_ProxyConfig类分析_spring3 aop 接口拦截

()方法的功能是查找代理的接口是否有定义()或()方法。

Spring AOP实现原理_spring3 aop 接口拦截_ProxyConfig类分析

通过在3.1节中的介绍可以得知,接口的()方法是代理对象执行方法调用和增强的地方,下面分析实现接口重写()方法的代码:

Spring AOP实现原理_spring3 aop 接口拦截_ProxyConfig类分析

通过以上代码分析可知,最核心的功能都是在.()方法中实现的,下面分析,代码如下:

spring3 aop 接口拦截_Spring AOP实现原理_ProxyConfig类分析

()方法是调用目标对象方法的地方,其实现如下:

spring3 aop 接口拦截_ProxyConfig类分析_Spring AOP实现原理

()方法会调用.()方法,代码如下:

spring3 aop 接口拦截_ProxyConfig类分析_Spring AOP实现原理

可以看到()方法最终是通过反射调用目标对象的方法。

通过对类的代码进行分析可以知道,类实现了接口,重写了()方法,当进行调用时,其实并不是调用目标对象,而是为目标对象创建一个代理对象,触发代理对象的()方法,在()方法中会通过反射调用目标对象的方法, AOP相关通知的调用也是在()方法中完成的。

3.6.3 

由于JDK动态代理只能针对接口生成代理对象,对于没有实现接口的目标对象,需要使用CGLIB产生代理对象,下面分析的代码。

回到ry.()方法,如果目标对象没有实现接口,将会返回一个xy对象。xy类的代码如下:

Spring AOP实现原理_spring3 aop 接口拦截_ProxyConfig类分析

从代码可以看出,xy继承了,是一个轻量级的Java库,作用是绕过构造器创建一个实例。因此分析的重点还是类。

ProxyConfig类分析_Spring AOP实现原理_spring3 aop 接口拦截

由本章3.1节可知,CGLIB的运行需要配合回调方法,实现接口,在中也是一样,下面分析获取回调方法()的代码:

Spring AOP实现原理_ProxyConfig类分析_spring3 aop 接口拦截

spring3 aop 接口拦截_ProxyConfig类分析_Spring AOP实现原理

通过上面对CGLIB创建代理和获取回调通知的代码分析,可以了解到CGLIB在获取代理通知时,会创建eptor类;当调用目标对象的方法时,不是直接调用目标对象,而是通过CGLIB创建的代理对象来调用目标对象;并且在调用目标对象的方法时,会触发eptor的回调方法对目标对象进行处理,CGLIB回调拦截器链的代码如下:

Spring AOP实现原理_ProxyConfig类分析_spring3 aop 接口拦截

spring3 aop 接口拦截_ProxyConfig类分析_Spring AOP实现原理

这里的n类继承了类,n.()调用了父类的.()方法,和3.6.2节中调用的方法是相同的,此处不再赘述。