SpringBoot使用Aop切面编程

使用Aop切面编程需要先了解涉及到的关键词:

@Aspect:定义切面类,切面类需要加上@Aspect、@Component注解

@Pointcut:告诉切面类,通知方法在什么时候运行的 表达式,他能锁定出一个或者一种方法,或者说锁定了一个位置出来。
@Around:环绕增强通知,会执行两次,一次在目标方法执行之前第二次在执行之后,Around功能比较强大,既可以在目标方法执行又会在目标方法执行之后执行,也可以修改目标方法参数以及修改目标方法返回值
@AfterReturning:后置增强通知,目标方法返回后调用
@Before:前置增强通知,目标方法执行之前执行
@AfterThrowing:异常抛出增强通知
@After:目标方法正常返回和抛出异常时都会执行

通知执行顺序:@Around-->Before方法-->method方法-->@AfterReturning方法-->@After-->@Around

  • pom引入相关依赖

	org.springframework.boot
	spring-boot-starter-aop
  • 定义注解
package com.stars.demo.annotation;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface ProcessHandle {
}
  • 定义切面类

其中 @Pointcut()切点分为execution方式和annotation方式。execution可以用路径表达式指定哪些类织入切面,annotation可以指定被哪些注解修饰的代码织入切面。这里使用的是第二种方式。定义切面类注意需要添加@Aspect、@Component注解

package com.stars.demo.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;


@Aspect
@Component
public class ProcessHandleContract {

    //切面连接点放到注解处
    @Pointcut("@annotation(com.stars.demo.annotation.ProcessHandle)")
    private void processHandleCut() {
    }

    //spring aop切面方法主要有:Around、Before、After、AfterReturning、AfterThrowing
    //执行顺序:@Around-->Before方法-->method方法-->@AfterReturning方法-->@After-->@Around
    @Around("processHandleCut()")
    public Object doAround(ProceedingJoinPoint point) throws Throwable {
        System.out.println("@Around:进入方法之前...");
        //获取目标方法的入参,可以对入参进行修改
        Object[] args = point.getArgs();
        Object proceed = point.proceed(args);
        System.out.println("@Around:执行方法之后...");
        return proceed;
    }
    @Before("processHandleCut()")
    public void doBefore(JoinPoint joinPoint){
        System.out.println("--------Before-----------");
    }

    @After("processHandleCut()")
    public void doAfter(JoinPoint joinPoint) {
        System.out.println("--------After-----------");

    }

    @AfterReturning("processHandleCut()")
    public void doAfterReturning(JoinPoint joinPoint) {
        System.out.println("--------AfterReturning-----------");

    }
    @AfterThrowing("processHandleCut()")
    public void doAfterThrowing(JoinPoint joinPoint) {
        System.out.println("--------AfterThrowing-----------");

    }

}
  • 使用切面
@GetMapping("/queryAll")
@ProcessHandle
public List queryAll(){
    System.out.println("开始执行Method");
    List userInfos = userInfoService.queryAll();
    return userInfos;
}

请求执行queryAll接口,打印结果: 从打印结果能看到各通知执行顺序

SpringBoot使用Aop切面编程_第1张图片

  • 补充几种切面不生效的常见原因
  1. 切面类需要添加@Aspect、@Component注解
  2. @Pointcut()切点设置有问题
  3. 目标类需要由Spring托管,不能是new()出来的也不能是类内部调用
  4. 切入的目标方法需要是public修饰,static、final修饰的方法都不能切入

你可能感兴趣的:(spring,boot,java,spring)