![Spring 5企业级开发实战](https://wfqqreader-1252317822.image.myqcloud.com/cover/807/26542807/b_26542807.jpg)
3.6 Spring AOP的实现原理
Spring AOP的实现是通过创建目标对象的代理类,并对目标对象进行拦截来实现的。分析Spring AOP的底层实现,需要重点分析几个常用类,相关类图如3-15所示。
ProxyConfig类是一个基类——数据类,主要为各种AOP代理工厂提供属性配置。
AdvisedSupport类是ProxyConfig类的子类,其封装了AOP中对通知(Advice)和通知器(Advisor)的相关操作,这些操作对于不同的创建代理对象的类都是相同的,但是对于具体的AOP代理对象的生成需要AdvisedSupport各个子类去实现。
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P114_33185.jpg?sign=1738863373-arUoz5m1crJS0l3Unw5hmvNhnAc7meW0-0-8967649b603ae0a75cec1bb7ab174865)
图3-15 Spring AOP核心类图
ProxyCreatorSupport类是AdvisedSupport的子类——辅助类,不同子类的一些通用的操作都封装在ProxyCreatorSupport中。
ProxyFactoryBean,ProxyFactory和AspectJProxyFactory是用于创建AOP代理对象的,这三个类的作用分别如下:
• ProxyFactoryBean类:功能是创建声明式的代理对象。
• ProxyFactory类:功能是创建编程式的代理对象。
• AspectJProxyFactory类:功能是创建基于AspectJ的代理对象。
3.6.1 设计原理
下面以ProxyFactoryBean为例,分析Spring AOP的实现原理。
首先定义一个接口Log,其中包含一个printLog()方法,Log接口的代码如下:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P114_94759.jpg?sign=1738863373-94tA1RtWAQEUShD9zNriHbi2WzDbNHTf-0-769949910c4d614060cd22f8c776d211)
再创建一个Target类,实现Log接口,重写printLog方法,Target类的代码如下:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P115_94764.jpg?sign=1738863373-LFJoAtRYMGymnfaNdknyD5feHlHPYcmr-0-9b3628c30dfe8609f472a9c9f7b120dd)
然后创建一个通知类LogAroundAdvice并实现MethodInterceptor接口,重写invoke()方法,在方法执行前后分别打印实现,LogAroundAdvice的实现如下:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P115_94765.jpg?sign=1738863373-MY0rd7OCuxzsIoVLrLIvlUgqsmWR3VZP-0-a5df38aafd0d9906bb39bb9acf8ea3e8)
创建一个测试类,用于观察测试结果,测试代码如下:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P116_94766.jpg?sign=1738863373-DiibeeClx6EQfTSUeYzqXJHiF3UP1KjR-0-03a3c3a53dbe5e35bdcb69c14d9f62f5)
文件spring-chapter3-sourcecodelearning.xml的配置如下:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P116_94767.jpg?sign=1738863373-y0qtWoj5AUD9kKiO9ZPp5i4rYvA4fEjv-0-5d174084f4ee5f888a97c5c219c74572)
运行测试代码,测试结果如下:
方法执行开始时间:2018-10-03 08:18:51 167 执行一些操作 方法执行结束时间:2018-10-03 08:18:52 172
从测试结果可以看出,在正常的调用printLog()方法前后分别打印了日志,说明AOP已经实现了。下面将通过这个案例分析ProxyFactoryBean的实现逻辑。
打开ProxyFactoryBean的代码,其生成代理对象的核心方法是getObject()方法,部分代码如下:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P117_94769.jpg?sign=1738863373-Onfo58vxqpkWqRGGv77aRR2ijyP3FZzH-0-6ef1f742facb1936c44d3d8e0096ba20)
下面分析getObject()方法中的initializeAdvisorChain()方法,initializeAdvisorChain()方法是初始化通知器链(或者叫拦截器链)的,其代码如下:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P117_94770.jpg?sign=1738863373-5OvQ3nonFoFc8m1yIE4TlgVRiONKrcqE-0-afbccaa2d5ef0aca1ba1478174da3248)
执行initializeAdvisorChain()方法后,如果是单例模式,将会调用getSingletonInstance()方法获取一个单例模式的代理对象,getSingletonInstance()方法代码如下:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P118_94772.jpg?sign=1738863373-JlqJVH6jPMyTDqDTAwOuAKzPD8aEtD0Y-0-e99c89764c072b641652857f8a4ff8cb)
执行initializeAdvisorChain()方法后,如果是非单例模式即原型模式,将会调用newPrototypeInstance()方法获取一个新的原型模式的代理对象,newPrototypeInstance()方法代码如下:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P119_94774.jpg?sign=1738863373-TfdxkjiDqG3fkFAktv5cOn6Y6r7kTdb6-0-f34b4e259227558cd4cf62af50318582)
可以发现,无论是单例模式还是原型模式,最终都是通过调用getProxy()方法获取代理对象的,getProxy()的实现如下:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P120_94776.jpg?sign=1738863373-LEKKMddy8tkZ5ib1IWPxAyhVv397H3VY-0-9bce486138a5f24ab5ba07b8fd53daa8)
通过以上对getSingletonInstance()方法和newPrototypeInstance()方法的代码注释可以发现,这两个方法都会调用ProxyCreatorSupport.createAopProxy()方法,ProxyCreatorSupport类的核心代码如下:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P120_94777.jpg?sign=1738863373-8VZHYmBxAftjrVed8Vw0zlMdBVrzJOSi-0-0c77b436c53accec71f2a428bc6dd759)
从createAopProxy()方法的代码可以看出,AopProxy对象是在DefaultAopProxyFactory类的createAopProxy()方法中生成的,DefaultAopProxyFactory.createAopProxy()方法的代码如下:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P121_94778.jpg?sign=1738863373-sYZbC39UJRXgwOAaN4XgFjrga491S67q-0-c86d49a452516f05e0a7da75c0d1180c)
从DefaultAopProxyFactory.createAopProxy()使用的类的名称可以发现,如果是继承了接口的类,会使用JDK动态代理,即用JdkDynamicAopProxy类创建代理对象,否则将会使用CGLIB动态代理即用ObjenesisCglibAopProxy类创建代理对象,关于这两种动态代理的具体使用,请参考本章3.1节。
3.6.2 JdkDynamicAopProxy
JDK动态代理只能针对接口起作用,Spring中通过JdkDynamicAopProxy类使用JDK动态代理创建AOPProxy对象,JdkDynamicAopProxy类的定义如下:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P121_94779.jpg?sign=1738863373-IK5iZhwwcyezwe777S8GoKHA6dUL4bHs-0-4e258c2ffdb8bb0c97314d5250307ef1)
JdkDynamicAopProxy类实现了InvocationHandler接口,因而可以使用JDK动态代理产生代理对象。
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P121_94780.jpg?sign=1738863373-MQI43eWrhxL0dbDmmRDLOljFivX6p9IF-0-41428da8c7a3203218258077c7bc9e0f)
此处的getProxy()方法是获取代理对象的入口,其是通过调用以下方法实现的:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P121_94781.jpg?sign=1738863373-TXY7KGZAMJabnMyuQbSnIVIVpzKwXJop-0-fa26d456ef59d59b43a8a1161c603dbc)
findDefinedEqualsAndHashCodeMethods()方法的功能是查找代理的接口是否有定义equals()或hashCode()方法。
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P122_94783.jpg?sign=1738863373-zXEZOE60iKd9YQ4naAtZXvU1bECRuL2V-0-c6c0e3243117d6c761730d49e535e048)
通过在3.1节中的介绍可以得知,InvocationHandler接口的invoke()方法是代理对象执行方法调用和增强的地方,下面分析JdkDynamicAopProxy实现InvocationHandler接口重写invoke()方法的代码:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P123_94785.jpg?sign=1738863373-dyW6k9fGTbGyfOqmJF5U7EoqD9Fqqh6f-0-e2666d48140e7b6afc2c00d0c4351c41)
通过以上代码分析可知,最核心的功能都是在invocation.proceed()方法中实现的,下面分析ReflectiveMethodInvocation,代码如下:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P124_94787.jpg?sign=1738863373-gIuJ9z3NS8TJhhYTyROUmq3gm3WSoFKN-0-6a24ba6b57d4988b7693e92b250b9357)
invokeJoinpoint()方法是调用目标对象方法的地方,其实现如下:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P125_94788.jpg?sign=1738863373-Iuo6iDoIZn18vs76JzOHAxSLj54yDxoB-0-e7a1f4dbceb3c90bb799b66484ae62e5)
invokeJoinpoint()方法会调用AopUtils.invokeJoinpointUsingReflection()方法,代码如下:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P125_94789.jpg?sign=1738863373-7LhNbLYrZuQLolzm0w8nl3WXk4SlOiCZ-0-1bb8491066ca86355dd09c20c0d96e21)
可以看到invokeJoinpointUsingReflection()方法最终是通过反射调用目标对象的方法。
通过对JdkDynamicAopProxy类的代码进行分析可以知道,JdkDynamicAopProxy类实现了InvocationHandler接口,重写了invoke()方法,当进行调用时,其实并不是调用目标对象,而是为目标对象创建一个代理对象,触发代理对象的invoke()方法,在invoke()方法中会通过反射调用目标对象的方法,Spring AOP相关通知的调用也是在invoke()方法中完成的。
3.6.3 CglibAopProxy
由于JDK动态代理只能针对接口生成代理对象,对于没有实现接口的目标对象,需要使用CGLIB产生代理对象,下面分析CglibAopProxy的代码。
回到DefaultAopProxyFactory.createAopProxy()方法,如果目标对象没有实现接口,将会返回一个ObjenesisCglibAopProxy对象。ObjenesisCglibAopProxy类的代码如下:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P126_94790.jpg?sign=1738863373-32cTFXDfq9gE7AJrNrr9Y6cLVzQjZTBo-0-684c898dc82f8fe8f5aa325e91a84a12)
从代码可以看出,ObjenesisCglibAopProxy继承了CglibAopProxy,Objenesis是一个轻量级的Java库,作用是绕过构造器创建一个实例。因此分析的重点还是CglibAopProxy类。
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P127_94791.jpg?sign=1738863373-gRGkTPuNRjtIVkKorCEpcFpXCyiILI3g-0-f59f0ad7ad8d792ac7676f6747e40239)
由本章3.1节可知,CGLIB的运行需要配合回调方法,实现MethodInterceptor接口,在CglibAopProxy中也是一样,下面分析获取回调方法getCallbacks()的代码:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P128_94793.jpg?sign=1738863373-T2xNr9VsFe074dMEKIpXDDZw97HOFJe3-0-f92fe69524810c1e721bd2826ba637e7)
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P129_94794.jpg?sign=1738863373-wC6qGNyFiCBDA5wEK0o4ChPIYKuYU7Az-0-9fab487f76d05df7d9826db1b18eeb4c)
通过上面对CGLIB创建代理和获取回调通知的代码分析,可以了解到CGLIB在获取代理通知时,会创建DynamicAdvisedInterceptor类;当调用目标对象的方法时,不是直接调用目标对象,而是通过CGLIB创建的代理对象来调用目标对象;并且在调用目标对象的方法时,会触发DynamicAdvisedInterceptor的intercept回调方法对目标对象进行处理,CGLIB回调拦截器链的代码如下:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P129_94795.jpg?sign=1738863373-exlTpWyYugR5owT6M8J7elLINMvHN27F-0-01b9ce1d5aad4f49ae5405700dd64949)
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P130_94796.jpg?sign=1738863373-dh2GwOV9UHwMx1OcOm93logx38SatCWi-0-970c4bf2e2e9a5bc87479b987e795136)
这里的CglibMethodInvocation类继承了ReflectiveMethodInvocation类,CglibMethodInvocation.procceed()调用了父类的ReflectiveMethodInvocation.proceed()方法,和3.6.2节中调用的方法是相同的,此处不再赘述。