目录
- 📚简介:
- 💨切面表达式:
- 💭切面通知类型:
- 🗺️创建项目演示:
- 🎢创建项目:
- 🎃添加依赖:
- 💨编写切面类:
- 🚀测试效果:
- 🎉结束:
📚简介:
我们写一个方法时如果每个接口都需要写一段固定的代码时,我们可以考虑使用切面(AOP)对方法进行增强,这些增强的方法称为连接点。好比我现在有个接口是用于提交数据或者对数据进行修改,这个时候如果发现数据有问题是不是应该进行排查,如果是直接打印日志的方式不是开发的同学就没办法判断为什么会产生错误数据,一般后台系统都有张表是用于记录用户操作数据的,这样我们就可以通过提交的数据进行排查为什么会产生错误数据,还有一个就是对数据进行操作产生问题追究职责的看是那个后台用户进行操作的。如果是按照之前的方式就是在对应的接口写保存日志的代码,代码就会变得重复且无意义,当保存记录添加新字段时我们又得到每一个接口上进行修改添加。
当使用切面以后我们只需要定义一个切面类对一些方法进行统一处理。切面可以通过添加execution
表达式进行对指定包下某个类某个方法进行增强。
💨切面表达式:
execution( [权限修饰符] [返回类型] [方法名称] ([参数列表]))
如:对com.itmei.service.CsService.update()方法进行增强
表达式如下:
execution(* com.itmei.service.CsService.update(..))
如:对com.itmei.service.CsService下的所有方法进行增强
表达式如下:
execution(* com.itmei.service.CsService.*(..))
如:对com.itmei.service包下的所有类方法进行增强
表达式如下:
execution(* com.itmei.service.*.*(..))
💭切面通知类型:
- 前置通知——@Before() (在调用被增强的方法前会调用该方法)
- 后置通知——@AfterReturning() (当方法运行完成后会调用该方法)
- 环绕通知——@Around
- 异常通知——@AfterThrowing()
- 最终通知——@After()(相当于finally)
后面代码中演示就比较好理解
🗺️创建项目演示:
🎢创建项目:
创建一个SpringBoot项目如果不知道然后创建可以点击查看
只需要看这个章节就可以创建好SpringBoot项目,我这里就不过多进行介绍如何创建项目。
🎃添加依赖:
在pom.xml中添加依赖
<!--添加SpringBoot的AOP依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
添加对应的包和类:
需要增强的类
💨编写切面类:
创建切面类:
/**
* @Author Itmei
* @Date 2022/12/18 10:47
* @Version 1.0
* AOP类
*/
@SuppressWarnings("AlibabaCommentsMustBeJavadocFormat")
@Component
@Aspect //切面注解
@Order(10) // 若有多个切面类,可以用Order注解决定不同类中的切面的执行顺序值越小越先执行
public class CommonAop {
//标识切入点的特征
@Pointcut(value = "execution(* com.itmei.springaopdemo.service.impl.CsServiceImpl.update(..))")
public void pointCut(){}
//前置通知
@Before(value = "pointCut()")
public void before(JoinPoint joinPoint){
System.out.println("前置通知:处理查询该用户那些权限");
System.out.println(" --方法的请求参数:"+Arrays.toString(joinPoint.getArgs()));
}
/**
* 后置通知(@After):当被增强的方法结束后会调用该通知
* @param joinPoint
*/
@After(value = "pointCut()")
public void after(JoinPoint joinPoint){
System.out.println("后置通知:当被增强的方法结束后会调用该通知");
}
/**
* 返回通知(@AfterReturning):当被增强的方法 成功执行之后调用通知
* @param joinPoint
* @param jsonResult
*/
@AfterReturning(value = "pointCut()",returning = "jsonResult")
public void afterReturning(JoinPoint joinPoint,Object jsonResult){
System.out.println("返回通知:当被增强的方法 成功执行之后调用通知");
}
/**
* 异常通知(afterThrowing) 当被增强的方法 出现异常之后调用通知
* @param joinPoint
*/
@AfterThrowing(value = "pointCut()",throwing = "e")
public void afterThrowing(JoinPoint joinPoint,Exception e){
System.out.println("异常通知:当被增强的方法 出现异常之后调用通知");
System.out.println(" --"+e.getMessage());
}
/**
* 环绕通知 使用环绕通知后可以不使用Before和after通知
* proceedingJoinPoint.proceed();的作用是让目标方法执行,@Around = @Before + 方法执行 + @After
*/
@Around(value = "pointCut()")
public void around(ProceedingJoinPoint proceedingJoinPoint){
//这里写Before通知的代码
System.out.println("环绕通知:Before");
try {
proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
System.out.println("环绕通知:报错信息"+throwable.getMessage());
}
//这里写after通知的代码
System.out.println("环绕通知:after");
}
}
🚀测试效果:
@SpringBootTest
class SpringAopDemoApplicationTests {
@Resource
private CsService csService;
@Test
void contextLoads() {
csService.update("123","itmei");
}
}
运行结果:
由此可以得出:
无异常
:@Around(proceed()之前的部分) → @Before → 方法执行 →@AfterReturning →@After →@Around(proceed()之后的部分
在需要增强的方法添加报错:
运行效果:
由此可以得出:
有异常:
@Around(proceed(之前的部分)) → @Before→ 方法执行 → @AfterThrowing→ @After →@Around(异常捕获的代码) →@Around(proceed(之后的部分))
🎉结束:
那么我们就可以把,进入日志的代码写在前置通知或者后置通知里面