标题之所以没叫Spring AOP实现,是因为Spring中AOP的两种实现方式之一是被这样叫的…… -_-T
Spring 中的AOP
AOP的Spring实现有两种:
- Spring AOP
本质上就是动态代理+AspectJ的部分功能。被代理的对象必须由Spring容器管理。下文会详述。
使用这种实现,可以用XML或annotation来做配置管理或aspect的声明等。
- 完整的AspectJ
集成了eclipse的AspectJ,以实现Weaving等。被代理的对象不需要由Spring容器管理。
那么,在使用的时候如何选择用哪种实现呢?
- Spring AOP比用完整的AspectJ要简单,因为它不引进AspectJ的编译器、织入器。所以如果你只是想要去干预Spring Bean的执行过程,那么Spring AOP是最佳选择。
注意:
这里有个条件是“Spring Bean”,就是说如果你用了Spring AOP,那么必须用Spring容器来管理这些需要被代理的Bean类。
- 如果你想要去干预非Spring容器管理的Objects的执行过程,那么就用AspectJ。
- 在之前AOP入门一文中,我提到过,joinpoints可以是任何一个类声明中的一行,比如field get或set,那么如果你想要去advise这些并不是方法的joinpoints,必须要使用AspectJ。
使用时的style
- Spring AOP
Spring AOP支持xml配置和annotation。
使用XML优点:
- 支持任何版本的JDK(可以忽略了,现在大多数都是JDK5+),当然,如果用了named pointcut,还是只能JDK 5+
- 如果你用了Spring容器来管理所有的bean或service,那么AOP的配置可以直接写在同一个配置文件中。显得集中而易于维护。
缺点:
- 它没有完全的把相关的所有定义放在同一个地方。违反了DRY( Don't Repeat Yourself) 原则,该原则要求在一个系统中,任何一个单独的定义应该是独立、清楚、可靠的。在XML定义中,如何实现代理的这一个requirement被分散到后端的各个bean的定义以及XML的配置中。
相比之下,@AspectJ这种风格就好的多,因为所有的定义都被封装在一起。
- XML风格的配置在组合pointcut时有一定的局限性。比如,在@AspectJ中,你可以这样写:
@Pointcut(execution(* get*()))
public void propertyAccess() {}
@Pointcut(execution(org.xyz.Account+ *(..))
public void operationReturningAnAccount() {}
@Pointcut(propertyAccess() && operationReturningAnAccount())
public void accountPropertyAccess() {}在XML中,你只能声明前面两个pointcuts:
<aop:pointcut id="propertyAccess"
expression="execution(* get*())"/>
<aop:pointcut id="operationReturningAnAccount"
expression="execution(org.xyz.Account+ *(..))"/>第三个联合的pointcut,XML配置无法直接实现。
@AspectJ的优点:
- 更好的支持aspect,更丰富的pointcut组合方式;
- 很好的封装了aspect,使其成为一个单独的modular,便于维护和修改;
- @AspectJ切面定义能同时被Spring AOP和AspectJ所理解,所以,后期可以很容易的把Spring AOP实现换成AspectJ实现。
个人比较倾向于annotation,因为XML定义最大的好处本来是可以灵活修改,方便维护,但在现在的企业开发中,一旦版本release后,后期修改XML的工作量和修改annotation的Java代码量并没有很明显的减少。
注意:
Spring也支持混合两种使用。
- AspectJ
使用完整的AspectJ,定义切面等,可以1)用AspectJ语言的语法做.aj文件来写切面或者 2)用@AspectJ annotation写JAVA文件。具体选择:
- 当AspectJ在你的设计中占据很大的角色时,并且你又刚好是用Eclipse来做开发,那么用AspectJ Development Tools (AJDT)Eclipse插件来使用AspectJ语法来定义是最佳选择:它更整洁和简单,因为AspectJ就是为了写切面而开发的语言。
- 如果你不是用Eclipse,或者只有少量的切面,在你的应用中并不占主要角色,你就可以选择用annotation,然后在build脚本中加入Aspect的Weaving部分。
Spring AOP底层实现
第一种 JDK 自带的动态代理技术
JDK动态代理必须基于接口 进行代理
作用:使用代理可以对目标对象进行性能监控(计算运行时间)、安全检查(是否具有权限)、记录日志等。
注意:必须要有接口才能进行代理,代理后对象必须转换为接口类型
例:
第二种 CGLIB(CodeGenerationLibrary)是一个开源项目
Spring使用CGlib进行AOP代理, hibernate也是支持CGlib(默认使用 javassist)需要下载cglib的jar包(Spring最新版本3.2内部已经集成了cglib,无需下载cglib的jar )
作用:可以为目标类,动态创建子类,对目标类方法进行代理(无需接口)。
原理:Spring AOP底层,会判断用户是根据接口代理还是目标类代理,如果针对接口代理就使用JDK代理,如果针对目标类代理就使用Cglib代理。
注意:CGLIB要求目标类及其父类一定要有空参构造函数。JAVA默认对所有继承Object的类,都有默认空参构造函数。但是,如果你实现了一个非空参的构造函数,那么空参构造函数就必须显示申明,否则,默认为没有空参构造函数。
参考文章:
http://blog.csdn.net/javaliuzhiyue/article/details/9357849
Spring中AOP实现
最新推荐文章于 2022-06-13 15:17:13 发布