目录
- 一、概述
- 二、Spring AOP 和 AspectJ AOP 的区别
- 三、AspectJ 定义的通知类型
- 四、多个切面的执行顺序控制方法
一、概述
AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么 Spring AOP 会使用 JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 Cglib 生成一个被代理对象的子类来作为代理,如下图所示:
当然你也可以使用 AspectJ !Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。
AOP 切面编程设计到的一些专业术语:
术语 | 含义 |
---|---|
目标(Target) | 被通知的对象 |
代理(Proxy) | 向目标对象应用通知之后创建的代理对象 |
连接点(JoinPoint) | 目标对象的所属类中,定义的所有方法均为连接点 |
切入点(Pointcut) | 被切面拦截 / 增强的连接点(切入点一定是连接点,连接点不一定是切入点) |
通知(Advice) | 增强的逻辑 / 代码,也即拦截到目标对象的连接点之后要做的事情 |
切面(Aspect) | 切入点(Pointcut)+通知(Advice) |
Weaving(织入) | 将通知应用到目标对象,进而生成代理对象的过程动作 |
二、Spring AOP 和 AspectJ AOP 的区别
Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。
Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。AspectJ 相比于 Spring AOP 功能更加强大,但是 Spring AOP 相对来说更简单,如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择 AspectJ ,它比 Spring AOP 快很多。
Spring AOP(面向切面编程)和AspectJ AOP都是面向切面编程的框架,用于在应用程序中实现横切关注点的模块化。尽管它们的目标相似,但它们在实现方式、集成方式以及功能上有一些区别。
- 实现方式:
- Spring AOP:Spring AOP是Spring框架提供的一种轻量级AOP实现。它通过使用代理技术(基于JDK动态代理或CGLIB)来实现AOP。Spring AOP仅支持方法级别的连接点(切点),并且提供了前置通知、后置通知、环绕通知、异常通知和最终通知等通知类型。
- AspectJ AOP:AspectJ AOP是一个独立于Spring的AOP框架,它提供了更强大和灵活的AOP功能。它可以通过编译时织入(AspectJ编译器)或运行时织入(使用字节码增强)来实现AOP。AspectJ支持更丰富的切点表达式和通知类型,包括引入(Introduction)和优化的连接点。
- 切点表达式:
- Spring AOP:Spring AOP的切点表达式相对简单,支持基于方法名、参数等的简单匹配。
- AspectJ AOP:AspectJ提供了更强大的切点表达式,可以匹配更复杂的结构,如类的属性、构造函数等。
- 集成方式:
- Spring AOP:Spring AOP与Spring框架紧密集成,可以无缝地与Spring应用程序一起使用。Spring AOP更适合那些已经在使用Spring框架的项目。
- AspectJ AOP:AspectJ是一个独立的框架,可以与任何Java应用程序一起使用。它可以在不使用Spring框架的情况下集成到应用程序中。
- 功能性:
- Spring AOP:适用于轻量级的AOP需求,可以实现一些常见的横切关注点,如日志记录、事务管理等。
- AspectJ AOP:适用于更复杂的AOP需求,提供了更多的切点表达式和通知类型,可以实现更精细的切面功能。
三、AspectJ 定义的通知类型
- Before(前置通知):目标对象的方法调用之前触发
- After (后置通知):目标对象的方法调用之后触发
- AfterReturning(返回通知):目标对象的方法调用完成,在返回结果值之后触发
- AfterThrowing(异常通知):目标对象的方法运行中抛出 / 触发异常后触发。AfterReturning 和 AfterThrowing 两者互斥。如果方法调用成功无异常,则会有返回值;如果方法抛出了异常,则不会有返回值。
- Around (环绕通知):编程式控制目标对象的方法调用。环绕通知是所有通知类型中可操作范围最大的一种,因为它可以直接拿到目标对象,以及要执行的方法,所以环绕通知可以任意的在目标对象的方法调用前后搞事,甚至不调用目标对象的方法
四、多个切面的执行顺序控制方法
- 通常使用@Order 注解直接定义切面顺序
// 值越小优先级越高 @Order(3) @Component @Aspect public class LoggingAspect implements Ordered {
- 实现Ordered 接口重写 getOrder 方法
@Component @Aspect public class LoggingAspect implements Ordered {// ....@Overridepublic int getOrder() {// 返回值越小优先级越高return 1;} }