【Spring AOP】_利用注解编写AOP步伐

[复制链接]
发表于 2025-10-20 18:59:17 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
目次
1. 以增长方法实行时间为例利用AOP
1.1 引入AOP依赖
1.2 编写AOP步伐
2. AOP的紧张概念
3. AOP关照范例与关照方法标注
3.1 在关照方法前利用对应注解
3.2 利用@Pointcut注解提取公共切点表达式
3.3 跨类利用切点
3.4 切面类排序


1. 以增长方法实行时间为例利用AOP

1.1 引入AOP依赖

在pom.xml中增长关于AOP的设置:
  1.         <dependency>
  2.             <groupId>org.springframework.boot</groupId>
  3.             <artifactId>spring-boot-starter-aop</artifactId>
  4.         </dependency>
复制代码
1.2 编写AOP步伐

以图书管理体系为例,为每个方法增长耗时盘算与日志日志打印。
创建aspect包,在其下创建TimeAspect类:
  1. package com.example.bookmanagementsystem.aspect;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.aspectj.lang.ProceedingJoinPoint;
  4. import org.aspectj.lang.annotation.Around;
  5. import org.aspectj.lang.annotation.Aspect;
  6. import org.springframework.stereotype.Component;
  7. @Aspect
  8. @Slf4j
  9. @Component
  10. public class TimeAspect {
  11.     @Around("execution(* com.example.bookmanagementsystem.controller.*.*(..))")
  12.     public Object timeCost(ProceedingJoinPoint joinPoint) throws Throwable {
  13.         long start=System.currentTimeMillis();
  14.         // 执行目标方法
  15.         Object result=joinPoint.proceed();
  16.         long end=System.currentTimeMillis();
  17.         log.info(joinPoint+"消耗时间:"+(end-start)+"ms");
  18.         return result;
  19.     }
  20. }
复制代码
关于注解:
1、@Aspect:体现该类是一个切面类;
2、@Around:用于指明切面类的作用域与作用方式(在哪个环节,对哪些方法);
关于切面类成员方法:
1、timeCost方法的参数是一个ProceedingJoinPoint范例的对象,体现目的方法;
2、代码被分为三大部分:

2. AOP的紧张概念

1、切点:一组通过表达式形貌的规则;
2、毗连点:切面作用/形貌的方法,即被AOP控制的目的方法;
3、关照:详细要做处置处罚的逻辑;
4、切面:切点+关照即切面,一个类可以有多个切面;
以上述切面类为例:

3. AOP关照范例与关照方法标注

1、@Around:围绕关照,此注解标注的关照方法在目的方法前、后都被实行;(最常用)
2、@Before:前置关照,此注解标注的关照方法在目的方法前被实行;
3、@After:
后置关照,此注解标注的关照方法在目的方法后被实行,无论是否发生非常都会实行;
4、@AfterReturning:
返回后关照,此注解标注的关照方法在目的方法后被实行,有非常不会实行;
5、@AfterThrowing:非常后关照,此注解标注的关照方法在非常后被实行;
3.1 在关照方法前利用对应注解

现在controller包下创建一个HelloController类,编写方法作为目的方法:
由于@AfterReturning与@AfterThrowing标注的方法在非常发生与否时返回差异,故编写两个方法使其满足一个正常运行,一个运行时报非常:
  1. package com.zhouyou.demos.controller;
  2. import org.springframework.web.bind.annotation.RequestMapping;
  3. import org.springframework.web.bind.annotation.RestController;
  4. @RestController
  5. public class HelloController {
  6.     @RequestMapping("/test1")
  7.     public String test1(){
  8.         return "hello";
  9.     }
  10.     @RequestMapping("/test2")
  11.     public int test2(){
  12.         return 10/0;
  13.     }
  14. }
复制代码
在aspect包下创建TestAspect类,用于编写关照方法:
  1. package com.zhouyou.demos.aspect;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.aspectj.lang.ProceedingJoinPoint;
  4. import org.aspectj.lang.annotation.*;
  5. import org.springframework.stereotype.Component;
  6. @Aspect
  7. @Slf4j
  8. @Component
  9. public class AspectDemo {
  10.     @Around("execution(* com.zhouyou.demos.controller.*.*(..))")
  11.     public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
  12.         log.info("AspectDemo around 前");
  13.         Object result=joinPoint.proceed();
  14.         log.info("AspectDemo around 后");
  15.         return result;
  16.     }
  17.     @Before("execution(* com.zhouyou.demos.controller.*.*(..))")
  18.     public void doBefore(){
  19.         log.info("AspectDemo before");
  20.     }
  21.     @After("execution(* com.zhouyou.demos.controller.*.*(..))")
  22.     public void doAfter(){
  23.         log.info("AspectDemo after");
  24.     }
  25.     @AfterReturning("execution(* com.zhouyou.demos.controller.*.*(..))")
  26.     public void doAfterReturning(){
  27.         log.info("AspectDemo afterReturning");
  28.     }
  29.     @AfterThrowing("execution(* com.zhouyou.demos.controller.*.*(..))")
  30.     public void doAfterThrowing(){
  31.         log.info("AspectDemo afterThrowing");
  32.     }
  33. }
复制代码
启动项目,依次根据路由映射访问test1方法和test2方法,可检察日志日志观察关照方法实行序次:

3.2 利用@Pointcut注解提取公共切点表达式

上述利用方法中,在利用对应注解标注关照方法时,须要重复编写公共切点表达式,这很不方便;
可利用@Pointcut提取公共切点表达式,在后续利用公共切点表达式时则直接利用@Pointcut标注的方法名即可;
修改3.1中的代码
  1. package com.zhouyou.demos.aspect;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.aspectj.lang.ProceedingJoinPoint;
  4. import org.aspectj.lang.annotation.*;
  5. import org.springframework.stereotype.Component;
  6. @Aspect
  7. @Slf4j
  8. @Component
  9. public class AspectDemo {
  10.     @Pointcut("execution(* com.zhouyou.demos.controller.*.*(..))")
  11.     private void pc(){
  12.     }
  13.     @Around("pc()")
  14.     public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
  15.         log.info("AspectDemo around 前");
  16.         Object result=joinPoint.proceed();
  17.         log.info("AspectDemo around 后");
  18.         return result;
  19.     }
  20.     @Before("pc()")
  21.     public void doBefore(){
  22.         log.info("AspectDemo before");
  23.     }
  24.     @After("pc()")
  25.     public void doAfter(){
  26.         log.info("AspectDemo after");
  27.     }
  28.     @AfterReturning("pc()")
  29.     public void doAfterReturning(){
  30.         log.info("AspectDemo afterReturning");
  31.     }
  32.     @AfterThrowing("pc()")
  33.     public void doAfterThrowing(){
  34.         log.info("AspectDemo afterThrowing");
  35.     }
  36. }
复制代码
3.3 跨类利用切点

现在aspect包中再创建一个切面类aspectDemo2,以@Before为例利用aspectDemo的切点。
  1. package com.zhouyou.demos.aspect;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.aspectj.lang.annotation.Aspect;
  4. import org.aspectj.lang.annotation.Before;
  5. import org.springframework.stereotype.Component;
  6. @Aspect
  7. @Slf4j
  8. @Component
  9. public class AspectDemo2 {
  10.     @Before("com.zhouyou.demos.aspect.AspectDemo.pc()")
  11.     public void doBefore(){
  12.         log.info("AspectDemo2 doBefore");
  13.     }
  14. }
复制代码
启动项目,根据方法路由映射即可在日志日志处观察到关照方法的详细实行序次情况;
利用方法注意事项:
(1)在跨类利用公共切点时,须要利用全限定类名;
(2)在当前类中,若在其类中实现的切点须要在其他类中利用,则切点必须以public修饰。
利用private修饰的切点只能在当前类中利用;
3.4 切面类排序

现aspect包下由AspectDemo、AspectDemo1、AspectDemo2三个切面类,并在每个切面类中实现@Before关照和@After关照。
创建目的方法并指定路由映射,并举行访问,检察日志输出:

在接纳默认排序的情况下,默认接纳按照切面类的类名字母排序:
对于@Before关照,排名越靠前的先实行;
对于@After关照,排名越靠后的先实行;
但这并未便于管理,Spring提供了@Order注解,用于给切面类设置优先级:
对于@Before关照,@Order中的数字越小越先实行;
对于@After关照,@Order中的数字越大越先实行;
现对AspectDemo切面类利用Order(3)、AspectDemo1切面类利用Order(2)、AspectDemo2切面类利用Order(1),启动步伐检察日志输出:

回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表