Spring之路(44)–Spring AOP通知类型详解与实例展示

简介: 本文目录1. 通知是干啥的2. 前置通知演示3. 正常返回通知演示4. 异常返回通知演示5. 返回通知演示6. 环绕通知演示7. 总结

1. 通知是干啥的

上一篇我们演示了一种通知,即使用@Before标识的在接入点执行的方法。通知就是切面要执行的特定行为。


实际上通知很灵活,还有其他种类的通知,具体如下:


注解 名称 说明

前置通知 @Before 在实际方法调用之前调用被注解的通知方法

正常返回通知 @AfterReturning 实际方法执行完毕后执行该通知,注意抛出异常则不会执行该通知

异常返回通知 @AfterThrowing 实际执行方法抛出异常执行该通知

返回通知 @After 实际方法调用之后执行该通知,不论是否发生异常

环绕通知 @Around 方法执行之前和之后都可以执行通知指定动作,这个比较强大

2. 前置通知演示

还是车辆出门前登记这个场景,注意通知参数可以携带JoinPoint参数,该参数中包含被通知的方法信息、还有目标对象的信息,这样便于我们操作。


第一,货车类和轿车类,提供容器中bean的类型信息。


package org.maoge.aopdemo.useaop;

/**

* 货车

*/

public class Truck {

public void out() {

 System.out.println("卡车出门");

}

public void in() {

 System.out.println("卡车进门");

}

}


package org.maoge.aopdemo.useaop;

/**

* 轿车

*/

public class Car {

public void out() {

 System.out.println("轿车出门");

}

public void in() {

 System.out.println("轿车进门");

}

}


第二,在配置类中将类型注册为bean,同时开启AOP,开启指定包的bean扫描。


package org.maoge.aopdemo.useaop;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.ComponentScan;

import org.springframework.context.annotation.Configuration;

import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**

* 配置类

*/

@Configuration // 配置类,用来配置容器

@EnableAspectJAutoProxy // 开启AOP

@ComponentScan(basePackages = { "org.maoge.aopdemo.useaop" }) // 扫描包以便发现注解配置的bean

public class SpringConfig {

@Bean // 注册卡车bean

public Truck Truck() {

 Truck truck = new Truck();

 return truck;

}

@Bean // 注册轿车bean

public Car car() {

 Car car = new Car();

 return car;

}

}


第三,配置切面,并编写前置通知


package org.maoge.aopdemo.useaop;

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.springframework.stereotype.Component;

/**

* 车辆出门切面

*/

@Component // 切面也是Spring的bean

@Aspect // 使用该注解标志此类是一切面

public class OutAspect {

  // 前置通知

  @Before("execution(public void out())")//在public void out()方法之前执行通知

  public void outNote(JoinPoint joinPoint) {

   System.out.println("出门登记信息");

   System.out.println("joinPoint.signature:" + joinPoint.getSignature());// 接入方法信息

   System.out.println("joinPoint.target.class.name:" + joinPoint.getTarget().getClass().getName());// 接入目标对象的类型信息

  }

}


第四,测试类


package org.maoge.aopdemo.useaop;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {

  public static void main(String[] args) {

   // 获取容器

   AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);

   // 取出bean

   Truck truck = (Truck) context.getBean(Truck.class);

   // 执行bean方法

   truck.out();

   Car car = (Car) context.getBean(Car.class);

   car.out();

  }

}


执行结果如下,可见前置通知执行成功,且已输出接入点方法信息和目标对象信息。


出门登记信息

joinPoint.kind:method-execution

joinPoint.signature:void org.maoge.aopdemo.useaop.Truck.out()

joinPoint.target.class.name:org.maoge.aopdemo.useaop.Truck

卡车出门

出门登记信息

joinPoint.kind:method-execution

joinPoint.signature:void org.maoge.aopdemo.useaop.Car.out()

joinPoint.target.class.name:org.maoge.aopdemo.useaop.Car

轿车出门


3. 正常返回通知演示

直接在切面类中添加通知即可,非常简单,注意如果抛出异常,该通知是不执行的。


  // 正常返回通知

  @AfterReturning("execution(public void out())")

  public void AfterReturning(JoinPoint joinPoint) {

   System.out.println("车辆已出门");

  }


4. 异常返回通知演示

在切面中定义异常返回通知,如下:


// 异常返回通知

@AfterThrowing("execution(public void out())")

public void afterThrowing(JoinPoint joinPoint) {

 System.out.println(joinPoint.getSignature()+"发生异常");// 接入方法信息

}


注意必须抛出才能执行该通知,如果方法内部处理了异常,则不会执行异常返回通知,如下:


package org.maoge.aopdemo.useaop;

/**

* 轿车

*/

public class Car {

//抛出异常,会执行异常通知

public void out() {

 System.out.println("轿车出门");

 int a=1/0;

}

public void in() {

 System.out.println("轿车进门");

}

}


package org.maoge.aopdemo.useaop;

/**

* 货车

*/

public class Truck {

//已处理异常,不会执行异常通知

public void out() {

 System.out.println("卡车出门");

 try {

  int a=1/0;

 }catch(Exception e) {

 }

}

public void in() {

 System.out.println("卡车进门");

}

}


5. 返回通知演示

返回通知是不管是否发生异常,都会执行的,示例如下:


// 返回通知(不论是否有异常都会执行)

  @After("execution(public void out())")

  public void after(JoinPoint joinPoint) {

   System.out.println("车辆出门这个事我知道了");// 接入方法信息

  }


6. 环绕通知演示

环绕通知能够在目标方法执行之前、之后启动,如果要记录一个方法的执行时间,那么使用环绕通知是很合适的,如下:


// 环绕通知,记录方法执行时间

  @Around("execution(public void out())")

  public void around(ProceedingJoinPoint joinPoint) throws Throwable {

   long startTime = System.currentTimeMillis();//开始时间

   joinPoint.proceed();//这一行代码表示执行目标方法

   System.out.println(joinPoint.getSignature() + "运行时间(毫秒)为:" + (System.currentTimeMillis() - startTime));

  }


我们来看下输出:


出门登记信息

joinPoint.signature:void org.maoge.aopdemo.useaop.Truck.out()

joinPoint.target.class.name:org.maoge.aopdemo.useaop.Truck

卡车出门

void org.maoge.aopdemo.useaop.Truck.out()运行时间(毫秒)为:7

车辆出门这个事我知道了

车辆已出门

出门登记信息

joinPoint.signature:void org.maoge.aopdemo.useaop.Car.out()

joinPoint.target.class.name:org.maoge.aopdemo.useaop.Car

轿车出门

车辆出门这个事我知道了

void org.maoge.aopdemo.useaop.Car.out()发生异常

Exception in thread "main" java.lang.ArithmeticException: / by zero


可见没有异常的时候,统计运行时间成功了,当发生异常时,环绕通知中抛出异常,未能执行到打印运行时间那一行,所以改为:


// 环绕通知,记录方法执行时间

  @Around("execution(public void out())")

  public void around(ProceedingJoinPoint joinPoint) {

   long startTime = System.currentTimeMillis();// 开始时间

   try {

    joinPoint.proceed();// 这一行代码表示执行目标方法

   } catch (Throwable e) {

    e.printStackTrace();

   }

   System.out.println(joinPoint.getSignature() + "运行时间(毫秒)为:" + (System.currentTimeMillis() - startTime));

  }


7. 总结

看到这里,想必大家也能深深体会AOP的强大和作用了,例如我们完全可以针对一些指定的方法启用事务,利用环绕通知在方法开始前开启事务,在方法执行后提交事务,发生异常时回滚。


Spring AOP是功能封装的利器,当项目中越来越多的使用到AOP时,说明已逐渐从初级的Java工程师向中级进阶啦,恭喜!

相关文章
|
2月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
403 0
|
1月前
|
XML Java 数据格式
《深入理解Spring》:AOP面向切面编程深度解析
Spring AOP通过代理模式实现面向切面编程,将日志、事务等横切关注点与业务逻辑分离。支持注解、XML和编程式配置,提供五种通知类型及丰富切点表达式,助力构建高内聚、低耦合的可维护系统。
|
6月前
|
监控 安全 Java
Spring AOP实现原理
本内容主要介绍了Spring AOP的核心概念、实现机制及代理生成流程。涵盖切面(Aspect)、连接点(Join Point)、通知(Advice)、切点(Pointcut)等关键概念,解析了JDK动态代理与CGLIB代理的原理及对比,并深入探讨了通知执行链路和责任链模式的应用。同时,详细分析了AspectJ注解驱动的AOP解析过程,包括切面识别、切点表达式匹配及通知适配为Advice的机制,帮助理解Spring AOP的工作原理与实现细节。
1027 13
|
3月前
|
人工智能 监控 安全
Spring AOP切面编程颠覆传统!3大核心注解+5种通知类型,让业务代码纯净如初
本文介绍了AOP(面向切面编程)的基本概念、优势及其在Spring Boot中的使用。AOP作为OOP的补充,通过将横切关注点(如日志、安全、事务等)与业务逻辑分离,实现代码解耦,提升模块化程度、可维护性和灵活性。文章详细讲解了Spring AOP的核心概念,包括切面、切点、通知等,并提供了在Spring Boot中实现AOP的具体步骤和代码示例。此外,还列举了AOP在日志记录、性能监控、事务管理和安全控制等场景中的实际应用。通过本文,开发者可以快速掌握AOP编程思想及其实践技巧。
|
3月前
|
人工智能 监控 安全
如何快速上手【Spring AOP】?核心应用实战(上篇)
哈喽大家好吖~欢迎来到Spring AOP系列教程的上篇 - 应用篇。在本篇,我们将专注于Spring AOP的实际应用,通过具体的代码示例和场景分析,帮助大家掌握AOP的使用方法和技巧。而在后续的下篇中,我们将深入探讨Spring AOP的实现原理和底层机制。 AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的核心特性之一,它能够帮助我们解决横切关注点(如日志记录、性能统计、安全控制、事务管理等)的问题,提高代码的模块化程度和复用性。
|
3月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
|
9月前
|
XML Java 测试技术
Spring AOP—通知类型 和 切入点表达式 万字详解(通俗易懂)
Spring 第五节 AOP——切入点表达式 万字详解!
633 25
|
8月前
|
Java 微服务 Spring
微服务——SpringBoot使用归纳——Spring Boot中使用拦截器——拦截器使用实例
本文主要讲解了Spring Boot中拦截器的使用实例,包括判断用户是否登录和取消特定拦截操作两大场景。通过token验证实现登录状态检查,未登录则拦截请求;定义自定义注解@UnInterception实现灵活取消拦截功能。最后总结了拦截器的创建、配置及对静态资源的影响,并提供两种配置方式供选择,帮助读者掌握拦截器的实际应用。
292 0
|
8月前
|
Java API 微服务
微服务——SpringBoot使用归纳——Spring Boot中的切面AOP处理——Spring Boot 中的 AOP 处理
本文详细讲解了Spring Boot中的AOP(面向切面编程)处理方法。首先介绍如何引入AOP依赖,通过添加`spring-boot-starter-aop`实现。接着阐述了如何定义和实现AOP切面,包括常用注解如`@Aspect`、`@Pointcut`、`@Before`、`@After`、`@AfterReturning`和`@AfterThrowing`的使用场景与示例代码。通过这些注解,可以分别在方法执行前、后、返回时或抛出异常时插入自定义逻辑,从而实现功能增强或日志记录等操作。最后总结了AOP在实际项目中的重要作用,并提供了课程源码下载链接供进一步学习。
981 0
|
8月前
|
Java 开发者 微服务
微服务——SpringBoot使用归纳——Spring Boot中的切面AOP处理——什么是AOP
本文介绍了Spring Boot中的切面AOP处理。AOP(Aspect Oriented Programming)即面向切面编程,其核心思想是分离关注点。通过AOP,程序可以将与业务逻辑无关的代码(如日志记录、事务管理等)从主要逻辑中抽离,交由专门的“仆人”处理,从而让开发者专注于核心任务。这种机制实现了模块间的灵活组合,使程序结构更加可配置、可扩展。文中以生活化比喻生动阐释了AOP的工作原理及其优势。
496 0