Spring AOP
1.Spring AOP是什么?
AOP(面向切面编程) 通过提供另外一种编程结构的思路,补充了OOP(面向对象编程)。OOP中模块化的关键是类,而在AOP中模块化的关键是Aspect切面。切面使关注点[concerns]的模块化(比如事务管理)可以横切多个类和对象。(这些关注点[concern]在AOP文档中通常被称作[crosscutting concerns])。
Spring中的关键组件之一是AOP框架,虽然Spring IOC容器不依赖于AOP,但AOP是对Spring IOC的补充,提供了非常强大的中间件解决方案。
Spring提供了两种简单而又强大的方式来自定义切面:scheme-based 方式、@AspectJ注解风格。这两种方式都提供了[fully typed advice]和AspectJ切入点语言&SpringAOP织入。
典型应用场景为:事务管理
AspectJ简介
AspectJ 是JAVA面向切面的通用扩展,是AOP编程的完全解决方案,功能强大。来自于Eclipse基金会。
2. Spring AOP目标&原理
目标:
- Spring AOP 是纯JAVA实现的,不需要特殊的编译过程。
- Spring AOP 当前仅支持方法执行上的连接点(建议在Spring Bean的方法执行),没实现对字段拦截的支持。如果你需要可以考虑AspectJ之类的语言。
- Spring 将AspectJ无缝集成到Spring AOP和IOC,这种集成没有影响到Spring AOP API、 AOP Alliance API。
原理:
Spring AOP 是基于代理的,默认使用JDK动态代理,可以代理任何接口。
Spring AOP 也可以使用CGLIB代理,用于代理类,而不是接口。默认情况下,如果业务对象未实现接口,则使用CGLIB。最佳实践是面向接口编程,在极少数情况下,可以强制使用CGLIB。
3 自定义一个切面
3.1 @AspectJ support [推荐方式]
@AspectJ 指将切面声明为带有注解的JAVA Class, @AspectJ风格是由AspectJ项目在AspectJ5版本引入的,Spring通过AspectJ实现的切入点解析&匹配的类库,来支持相同的注解。
【???咋做到的】但是AOP运行时仍然是纯SpringAOP,且并不依赖于ApsectJ编译器或织入器。
启用@AspectJ
@AspectJ 可以通过XML或注解[Java-style configuration]启用,无论哪种方式,你都需要确保引入aspectjweaver.jar (version 1.8 or later)
JAVA注解方式启用@AspectJ
@Configuration @EnableAspectJAutoProxy public class AppConfig { }
XML方式启用@AspectJ
<aop:aspectj-autoproxy/>
声明一个切面
@AspectJ启用后,你的应用上下文中被@Aspect标注的类,就会自动被Spring检测到并用来配置Spring AOP。下面生命一个啥也没干的切面。
<bean id="myAspect" class="org.xyz.NotVeryUsefulAspect">
<!-- configure properties of the aspect here -->
</bean>
package org.xyz; import org.aspectj.lang.annotation.Aspect; @Aspect
@Component public class NotVeryUsefulAspect { }
可以像Spring管理其他Bean一样,在配置文件中注册或通过类路径扫描自动检测。但是@Aspect注解不足以在类路径中自动检测。为此需要添加@Component。
声明一个切入点
SpringAOP 只支持在Spring Bean的方法执行进行切入,一个切入点声明包含两部分:切入点标志+切入点表达式。
下面的切入点,定义了一个名为"anyOldTransfer"的切入点,任何方法名为transfer的执行会被切入。
@Pointcut("execution(* transfer(..))") // the pointcut expression
private void anyOldTransfer() {} // the pointcut signature
Spring AOP 的切入点表达式支持以下AspectJ pointcut designators(PCD),以下几个为常用的切入点标识符。
| execution | SpringAOP 主要的切入点标识符,用于匹配方法执行切入点 |
| @within | 类具有给定注解,则匹配类内所有方法执行切入点 |
| @annotation | 方法具有给定注解,则匹配方法执行切入点 |
3.2 scheme-based AOP support
3.3 Low-Level Spring AOP API
spring提供了一些通知类型,比如Interception around advice,Spring 最基础的切面。
public class DebugInterceptor implements MethodInterceptor { public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("Before: invocation=[" + invocation + "]"); Object rval = invocation.proceed(); System.out.println("Invocation returned"); return rval; } }
4. AOP框架对比
| 来源&背景 | 织入&编译 | 功能 | 学习难易程度 | |
| AspectJ |
来自于Eclipse基金会 AOP编程的完全解决方案 |
实际运行前就完成了织入 需要AspectJ编译器 |
功能强大,性能更好 可编织字段、方法、构造函数 |
易于学习和使用 |
| SpringAOP | 只能作用于Spring容器 |
只能运行时织入 不需要单独的编译过程 |
功能不强,较慢 只支持方法级编织 |
复杂 |
5 AOP注意事项
1. JDK动态代理,只能作用于 public方法,且需要实现接口Interface
2. Cglib代理,只能拦截protected\public方法
3. 由于Spring AOP 基于代理的性质,不会拦截目标对象内的调用
参考链接:
Aspect Oriented Programming with Spring

浙公网安备 33010602011771号