1、介绍
AOP(面向切面编程)对OOP(面向对象编程)是一种补充,它提供了另一种程序结构的思路。OOP的模块单元是class,而AOP的模块单元是aspect。Spring中一个关键的组件是AOP框架,然而,Spring IoC容器并不依赖于AOP,也就是说如果你不想用AOP的话可以不用。
在Spring框架中AOP用来做什么呢?
1.1、AOP概念
- Aspect(方面):横切多个class的一个关注点的模块化。事务管理是一个很好的例子。在Spring AOP中,aspect可以用普通类或者带有@Aspect注解的普通类来实现。
- Join point(连接点):程序执行期间的一个点,比如方法的执行或者异常的处理。在Spring AOP中,一个连接点总是代表一个方法执行。
- Advice(通知):一个aspect在一个特定的连接点所采取的动作。通知的类型包括"around"、"before"、"after"。许多AOP框架,包括Spring也是,它们把一个通知作为一个拦截器,维护一个拦截器链环绕在连接点上。
- Pointcut(切入点):匹配连接点的一个谓词。Advice关联一个切点表达式。Spring默认用AspectJ切点表达式。
- Target object(目标对象):被一个或多个aspect通知的对象。在Spring AOP中是用运行时代理来实现的,因此这个对象总是一个代理对象。
- AOP proxy(AOP代理):为了实现aspect而被AOP框架所创建的一个对象。在Spring框架中,一个AOP proxy可能是一个JDK动态代理或者一个CGLIB代理。
1.2、通知的类型
- Before advice(前置通知):在一个连接点之前执行的通知,但是没有能力阻止后面的执行(除非它抛异常)
- After returning advice(返回通知):在一个连接点正常执行完以后执行的通知:例如,在一个不抛异常的方法返回时执行
- After throwing advice(异常通知):如果方法因为抛出异常而退出了才会执行的通知
- After (finally) advice(后置通知):无论连接点正常退出还是异常退出都会执行
- Around advice(环绕通知):环绕一个连接点比如方法调用的通知。这是最强的一种通知。环绕通知可以在方法调用之前或之后执行自定义的行为。它也负责选择是否处理连接点方法执行,通过返回一个它自己的返回或者抛出异常。环绕通知是用得最普遍的一种通知。
1.3、Spring AOP的能力和目标
Spring AOP用纯Java实现。目前只支持方法执行的连接点,字段拦截没有实现。
1.4、AOP Proxies
@H_404_83@Spring AOP defaults to using standard JDK dynamic proxies for AOP proxies. This enables any interface (or set of interfaces) to be proxied.
@H_404_83@Spring AOP can also use CGLIB proxies. This is necessary to proxy classes rather than interfaces.
@H_404_83@CGLIB is used by default if a business object does not implement an interface. As it is good practice to program to interfaces rather than classes; business classes normally will implement one or more business interfaces.
默认JDK动态代理,如果对象没有实现接口则用CGLIB
2、@AspectJ支持
@AspectJ是用注解来标注常规的Java类的一种声明aspect的风格。
2.1、启用@AspectJ支持
你需要开启Spring对于基于@AspectJ aspects的Spring AOP配置的支持,和autoproxying beans的支持。autoproxying的意思是如果Spring检测到一个bean被一个或多个aspect通知,它将自动为这个bean生产代理以拦截方法调用并确保通知被执行。
可以用XML或者Java配置的方式来开启对@AspectJ的支持。你需要确保在你的工程的classpath下有aspectweaver.jar。
2.2、声明一个aspect
2.3、声明一个pointcut
@H_404_83@A pointcut declaration has two parts: a signature comprising a name and any parameters,and a pointcut expression that determines exactly which method executions we are interested in. In the @AspectJ annotation-style of AOP,a pointcut signature is provided by a regular method definition,and the pointcut expression is indicated using the @Pointcut annotation (the method serving as the pointcut signature must have a void return type).
声明一个pointcut有两部分:一个签名和一个切点表达式。签名由一个name和任意参数组成,切点表达式决定对哪些方法执行感兴趣。在注解风格的AOP中,一个pointcut签名就是一个常规方法定义,而pointcut表达式用@Pointcut注解来标识(作为pointcut签名的方法的返回值必须是void)
Spring AOP还支持下面这样的切点表达式:
切点表达式可以组合使用
@H_404_83@The format of an execution expression is:
2.4、声明advice
3、基于XML格式的AOP支持
@H_404_83@the keywords 'and','or' and 'not' can be used in place of '&&','||' and '!' respectively
4、选择哪种AOP声明方式
4.1、Spring AOP or full AspectJ?
4.2、@AspectJ or XML for Spring AOP?
如果你选择用Spring AOP,那么你可以选择用@AspectJ或者XML风格。推荐用@AspectJ。
5、代理机制
Spring AOP用JDK动态代理或者CGLIB来创建目标对象的代理。(首选JDK动态代理)
如果被代理的目标对象至少实现了一个接口,那么JDK动态代理将会被使用。而且,目标对象实现的所有接口都将被代理。
如果目标对象没有实现任何接口,那么一个CGLIB代理将会被创建。
如果你想强制使用CGLIB代理也是可以的,但是你需要考虑一个问题,那就是final方法不能被通知,因为它们不能被覆盖。
如果你想强制使用CGLIB代理可以这样做,二者选其一即可:
5.1、理解AOP代理
Spring AOP is proxy-based.(Spring AOP是基于代理的)
理解这个语义是极其重要的。
参考
《Spring Framework Reference Documentation》 4.3.14.RELEASE
Spring文档下载地址
http://repo.springsource.org/libs-release-local/org/springframework/spring/