当前位置: 首页 > news >正文

Spring @Aspect注解

Spring boot @Aspect

  • 使用场景
  • 列子1 (演示基本过程
  • 切点表达式
    • 切点复合运算
    • 切点匹配方法
  • 通知注解
  • 切面类执行顺序

 

使用场景

  • 常见用于记录日志, 异常集中处理, 权限验证以及 Web参数有效验证等等

列子1 (演示基本过程

@Aspect
@Component
public class TestAspect {/*** 声明一个切入点, 命名 pointcut1* */@Pointcut("execution(public java.util.Map com.example.demo.controller.TestService.getMap(String, Integer))")private void pointcut1() {}/*** 锁定的切点方法之前执行* JoinPoint 获取连接点信息 *    -    Object[] getArgs()             获取连接点方法运行时的入参列表*    -    Signature getSignature()     获取连接点的方法签名对象*    -    Object getTarget()             获取连接点所在的目标对象*    -    Object getThis()             获取代理对象* */@Before("pointcut1()")public void aspect1(JoinPoint joinPoint) {System.out.println("TestAspect -> @Before 方法名称:" + joinPoint.getSignature().getName() + ", 参数:" + Arrays.asList(joinPoint.getArgs()));}/*** 锁定的切点方法之后执行* */@After("pointcut1()")public void aspect2() {System.out.println("TestAspect -> @After");}/*** 锁定的切点方法返回后执行* */@AfterReturning(pointcut = "pointcut1()", returning="result")public void aspect3(Object result){System.out.println("TestAspect -> @AfterReturning 返回值:" + result);}}@Service
public class TestService {public Map<String, Object> getMap(String name, Integer age) {final Map<String, Object> result = new HashMap<>(2);result.put("name", name);result.put("age", age);System.out.println("TestService -> getMap 函数体内输出:" + result);return result;}}# 测试地址 http://127.0.0.1:8080/aspectTest
@RestController
public class AspectController {@Autowiredprivate TestService testService;@GetMapping(value = "/aspectTest")public Map<String, Object> aspectTest(@RequestParam(value="name", required=false, defaultValue="大爷") String name,@RequestParam(value="age", required=false, defaultValue="35") Integer age) {System.out.println("AspectController -> aspectTest");return testService.getMap(name, age);}}# 输出
AspectController -> aspectTest
TestAspect -> @Before 方法名称:getMap, 参数:[大爷, 35]
TestService -> getMap 函数体内输出:{name=大爷, age=35}
TestAspect -> @After
TestAspect -> @AfterReturning 返回值:{name=大爷, age=35}

切点表达式

  1. ..两个点表明多个, *代表一个
  2. 其中权限修饰符是可选, 当不写时不能用*代替, 因此第一个*代表返回类型不限
  3. 第二个*表示指定包下所有类
  4. 第三个*表示指定类下所有方法
  5. (..)两个点表示指定方法的参数不限
@Pointcut(execution(* com..demo.controller.*.*(..)))

切点复合运算

  • 切点表达式可以加运算符 与&&或||非! 做复合运算
@Before(value="execution(* com.example.demo.controller.TestService.getMap(..)) && args(name, age, ..)")

切点匹配方法

  • execution: 用于匹配方法的执行
  • within: 用于匹配指定类内的方法的执行
  • args: 用于指定匹配方法的参数类型
  • target: 用于匹配容器内的类的对象执行方法, 不包括引入接口
  • this: 用于匹配容器内的类的对象执行方法, 包括引入接口

注: target和 this两种方法表达式必须全限定名到类名, 不支持*通配符

通知注解

  • @Before: 前置通知, 在方法执行之前执行
  • @After: 后置通知, 在方法执行之后执行
  • @AfterRunning: 返回通知, 在方法返回结果之后执行
@AfterReturning(pointcut = "pointcut1()", returning="result")
public void aspect3(JoinPoint joinPoint, Object result){System.out.println("TestAspect1 -> @AfterReturning 返回值:" + result);
}# 执行过程
Request -> @Before -> Method -> @After -> @AfterReturning    
  • @AfterThrowing: 异常通知, 在方法抛出异常之后执行, 意味着跳过返回通知
/**
* 指定方法内抛出异常时才会被通知
* 属性 throwing上设置异常类 Throwable将会捕获任何错误和异常, 或按需设置指定异常类
*/
@AfterThrowing(pointcut = "pointcut1()", throwing="ex")
public void aspect4(JoinPoint joinPoint, TestException ex) {System.out.println("TestAspect1 -> @AfterThrowing 异常:" + ex.getMessage());
}# 执行过程
Request -> @Before -> Method -> @After -> @AfterThrowing
  • @Around: 环绕通知, 围绕着方法执行
/**
* ProceedingJoinPoint继承于 JoinPoint接口, 并多了两个方法
*    -    Object proceed() throws Throwable         通过反射执行目标对象连接点处的方法
*    -    Object proceed(Object[] var1) throws Throwable     通过入参替换原参, 通过反射执行目标对象连接点处的方法
*/
@Around("pointcut1()")
public Object aspect5(ProceedingJoinPoint pjp) throws Throwable {System.out.println("TestAspect1 -> @Around start");Object[] args = pjp.getArgs();for (Object arg : args) {System.out.println("TestAspect1 -> @Around 参数:" + arg); // 输出指定方法参数
    }long startTime = System.currentTimeMillis();Object object = pjp.proceed(); // 调用 proceed后指定方法会被执行long endTime = System.currentTimeMillis();System.out.println("TestAspect1 -> @Around " + (endTime - startTime) + " ms");return object;
}# 输出
AspectController -> aspectTest
TestAspect1 -> @Around start
TestAspect1 -> @Around 参数:大爷
TestAspect1 -> @Around 参数:35
TestAspect1 -> @Before
TestService -> getMap 函数体内输出:{name=大爷, age=35}
TestAspect1 -> @Around 0 ms
TestAspect1 -> @After
TestAspect1 -> @AfterReturning 返回值:{name=大爷, age=35}# 正常执行过程
Request -> @Around -> @Before -> Method -> @Around -> @After -> @AfterReturning
# 异常执行过程
Request -> @Around -> @Before -> Method -> @Around -> @After -> @AfterThrowing

切面类执行顺序

  • 通过 @Order注解设置, 数越小越靠前
@Aspect
@Component
@Order(3)
public class TestAspect1 {}

 

http://www.gsyq.cn/news/158655.html

相关文章:

  • 深度解析PHP木马代码及其危害
  • 还在用云端大模型?本地部署智谱Open-AutoGLM的7大不可抗拒理由
  • DMX512协议和 RDM协议
  • PPAP流程详解及提交等级解析
  • 2025升降机厂家推荐榜:权威精选,适配全场景需求 - 品牌智鉴榜
  • UTF-8编码解析与汉字对照表
  • 2025-2026北京市东城区公司清算律师事务所权威测评排行榜 靠谱机构推荐含在线律师咨询/胜诉率/解决方案全面解析 - 苏木2025
  • 重新定义户外直播!基于电鱼智能 RK3576 的 5G 高清垂钓记录终端方案
  • 发现并分析一个PHP木马后门
  • 从零部署Open-AutoGLM:智谱开源模型源码获取与环境配置实战(全流程图解)
  • 汉字转拼音首字母并按字母排序展示商家
  • 手机与PS旋转校正技巧:2分钟修正好照片
  • 多级延迟触发器与边沿检测电路设计
  • PHP大马分析:短小精悍的后门程序
  • 【Java毕设源码分享】基于springboot+vue的宿舍报修系统的设计与实现(程序+文档+代码讲解+一条龙定制)
  • C语言指针入门:从概念到数组与字符串
  • AGV系统基础知识与智能物流应用解析
  • 【Java毕设源码分享】基于springboot+vue的百货中心管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)
  • C++中如何正确调用C语言函数?
  • Word操作题第10套完整排版指南
  • 将Forest应用的数据库从Derby迁移至MySQL
  • 2006年4月全国计算机等级考试二级JAVA笔试真题解析
  • C语言开发必备工具与汇编嵌入技巧
  • 2025高奢酒店商用、大型办公室咖啡机推荐 - 品牌2026
  • 架构升维!基于电鱼智能 RK3568 的路亚船控制器:从简单逻辑向边缘算力演进
  • 你上过高中,你说你搞不明白transformer的自注意力机制?
  • 9个降AI率工具推荐!研究生高效避坑指南
  • 探索英威腾CHE100 - 2406变频器:学习路上的宝藏资料
  • 大家常用的数据迁移工具
  • 第1章 Shell基础语法核心(20例,初级运维)-补充内容002【子Shell相关知识补充】