AOP(Aspect Oriented Programming):面向切面编程
利用AOP切面可以对业务进行无侵入增强,在不改变原有逻辑的基础上,在其前后进行处理
概念
- 切面(Aspect):一般指被@Aspect修饰的类,某一具体功能的AOP逻辑
- 连接点(JoinPoint):被切入点选中的方法
- 切入点(Pointcut):选择对哪些方法进行增强
通知(Advice):对目标方法的增强,有以下五种增强类型
- 环绕通知(@Around):内部执行方法,可自定义在方法执行的前后操作
- 前置通知(@Before):在方法执行前执行
- 后置通知(@After):在方法执行后执行
- 返回通知(@AfterReturning):在方法返回后执行
- 异常通知(@AfterThrowing):在方法抛出异常执行
对于不同的方法,使其生效的匹配方式有很多
表达式类型 功能 execution() 匹配方法,最全的一个 args() 匹配入参类型 @args() 匹配入参类型上的注解 @annotation() 匹配方法上的注解 within() 匹配类路径 @within() 匹配类上的注解 this() 匹配类路径,实际上AOP代理的类 targer() 匹配类路径,目标类 @target() 匹配类上的注解
实现
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
创建切入注解
ElementType.TYPE 声明这个注解可以在类上使用
ElementType.METHOD 声明这个注解可以在方法上使用
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Aop {
}
编写切面类
- 通过@Aspect告诉spring容器这是一个切面类,同时使用@Component注解将其声明成spring容器的组件
- 创建一个成员方法(不用有具体的实现),在上面添加上@Pointcat注解,声明这是个切入点方法,在这里我们就可以选择不同的匹配方式,我们这里使用的是@Aop注解的方式
- 实现具体的增强方法,通过@After、@Before...,并且在其中引入切入点方法
@Aspect
@Component
public class ScheduledAop {
@Pointcut("@annotation(com.webwss.scheduled.annotation.Aop)")
public void authcat(){
}
@After("authcat()")
public void print(JoinPoint joinPoint){
System.out.println("catprint running");
}
@Before("authcat()")
public void before(JoinPoint joinPoint){
String name = joinPoint.getSignature().getName();
System.out.println(name);
}
@Around("authcat()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("开始执行");
Object proceed = joinPoint.proceed();
System.out.println("执行结束");
}
@AfterThrowing(value = "authcat()",throwing = "e")
public void execption(JoinPoint joinPoint,Exception e){
System.out.println(joinPoint.getSignature().getName() + ".exception:" + e.getMessage());
}
@AfterReturning("authcat()")
public void afterReturn(JoinPoint joinPoint){
System.out.println(joinPoint.getSignature().getName() + "执行结束");
}
}
使用AOP
在具体的业务方法上添加上我们自定义的@Aop注解,告诉aop从这里切入,这里我们自己抛出了个异常,用来测试@AfterException,异常的前置通知
@Component
public class MySchduled {
private int count = 0;
@Aop
@Scheduled(cron = "0/3 * * * * ? ")
public void print(){
System.out.println("hello:" + count++);
if(count == 3){
throw new RuntimeException("hello");
}
}
}
开启AOP
我们需要在启动类或者配置类上添加@EnableAspectJAutoProxy,开启aop
@SpringBootApplication
@EnableAspectJAutoProxy
public class AuthApplication {
public static void main(String[] args) {
SpringApplication.run(AuthApplication.class,args);
}
}
AOP应用场景
- 记录日志:通过在方法调用前后插入切面逻辑,可以方便地实现日志记录功能,例如在方法调用前记录方法名和参数,以及在方法调用后记录方法的返回值
- 监控方法运行时间(监控性能):AOP可以用于监控方法的运行时间,从而找出性能瓶颈,提高系统的性能
- 权限控制:通过在方法调用前插入切面逻辑,可以实现安全性检查功能,例如检查用户的权限,只允许有特定权限的用户访问某些方法
- 性能统计和计数:AOP可以用于统计方法的执行时间、调用次数等信息,帮助定位系统瓶颈和优化点