Spring boot AOP

211 阅读2分钟

参考

AOP概念

  • Target(目标对象):代理的目标对象

  • Proxy (代理):一个类被 AOP 织入增强后,就产生一个结果代理类

  • Joinpoint(连接点):所谓连接点是指那些可以被拦截到的点。在spring中,这些点指的是方法,因为 spring只支持方法类型的连接点

  • Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义

  • Advice(通知/ 增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知 分类:前置通知、后置通知、异常通知、最终通知、环绕通知

  • Aspect(切面):是切入点和通知(引介)的结合

  • Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织 入,而AspectJ采用编译期织入和类装载期织入

  • @Before:这种拦截器先执行拦截代码,再执行目标代码。如果拦截器抛异常,那么目标代码就不执行了;

  • @After:这种拦截器先执行目标代码,再执行拦截器代码。无论目标代码是否抛异常,拦截器代码都会执行;

  • @AfterReturning:和@After不同的是,只有当目标代码正常返回时,才执行拦截器代码;

  • @AfterThrowing:和@After不同的是,只有当目标代码抛出了异常时,才执行拦截器代码;

添加maven依赖

 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

添加切面配置

config/AopConfig.java

@Configuration
@ComponentScan("com.lagou.aop")
@EnableAspectJAutoProxy
public class AopConfig {
}

添加切面类

aop/LogAop.java

@Component
@Aspect
public class LogAop {

    @Pointcut("execution(* com.lagou.controller.UserController.*(..))")
    public void log(){}

    @Before("log()")
    public void before() {
        System.out.println("[before] execute");
    }

    @AfterReturning(value = "log()",returning = "retVal")
    public void afterReturning(Object retVal) {
        System.out.println("[AfterReturning] retVal:"+retVal);
    }

    @AfterThrowing(value = "log()",throwing = "ex")
    public void afterThrowing(Exception ex) {
        System.out.println("[AfterThrowing] execute:"+ex);
    }

    @After("log()")
    public void after() {
        System.out.println("[After] finally execute");
    }

    @Around("log()")
    public Object around(ProceedingJoinPoint pjb) throws Throwable {
        Object processed=null;
        try {
            System.out.println("[Around] 前置");
            //切点方法执行
            processed = pjb.proceed();

            System.out.println("[Around] 后置");
            return processed;
        } catch(Exception e) {
            System.out.println("[Around] 异常");
            return processed;
        } finally {
            System.out.println("[Around] 最终");
        }
    }
}
[Around] 前置
[before] execute
[AfterReturning] retVal:[]
[After] finally execute
[Around] 后置
[Around] 最终

执行顺序

Before -->AfterReturning(有异常时AfterThrowing) -->After

Advice 参数

ProceedingJoinPoint

ProceedingJoinPoint 的父类 JoinPoint

The JoinPoint interface provides a number of useful methods such as

getArgs() (returns the method arguments),

getThis() (returns the proxy object),

getTarget() (returns the target object),

getSignature() (returns a description of the method that is being advised)

toString() (prints a useful description of the method being advised). Please do consult the Javadocs for full details.

参数传递

@Pointcut("execution(* com.lagou.controller.UserController.getUserById(..)) && args(id,..))")
public void log(Integer id) {
}

@Before(value = "log(id)")
public void before(Integer id) {
    System.out.println("[before] execute" + id);
}