天天看点

程序员晋级之路——初识AOP

前言

何为AOP?AOP就是面向切面的编程。

何为面向切面的编程?就像高速公路的省界收费站一样,每条进出我们省的高速都会在省界上设立一个收费站,那么省界就是一个切面,收费站就是我们的处理方案,我们需要做的是定义省界这个面和在面上的收费站的功能。

应用场景

在项目完成之后,交付之前我们一般会对程序进行压力测试,在测试中怎么更加精准的定位系统运行的瓶颈呢?这时候你需要AOP监测每个接口甚至每个方法执行的时间!

在项目做异常处理时,我们怎样才能更加简单明了,将所有异常统一截取到同一个方法中进行处理?这时候你需要AOP将抛出的异常接受并处理!

AOP的定义非常灵活,可以是返回值类型,也可以是注释,也可以是某一个包下的所有方法或者指定方法,所以学习AOP之后,你不需要担心没有用武之地!

AOP结构

首先需要在这个类上添加一个@Aspect注释,这就声明了这个类是一个切面。

如下例子,将所有返回值为指定类型的方法定义为一个切面:

@Aspect
@Component
@Slf4j
public class ResultAspect {
    // 切入点  所有返回值类型是com.test.xbo包下ResultBO的方法
    @Pointcut("execution(public com.test.xbo.ResultBO *(..))")
    public void ResultAspect() {
    }
    // 环绕通知,参数必须为ProceedingJoinPoint,proceed就是被切面的方法
    @Around("ResultAspect()")
    public Object deAround(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        joinPoint.proceed();
        String str = "## 控制器运行时间:" + joinPoint.getSignature() + ":" + (System.currentTimeMillis() - startTime);
        return null;
    }
}

      

再如,我定义一个注释,将所有添加该注释的方法定义为一个切面:

1、定义一个注释,添加该注释的方法会打印出该方法执行的时间:

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface DoneTime {
    String param() default "";
}      

2、定义一个切面

@Aspect
@Component
@Slf4j
public class DoneTimeAspect {
    @Around("@annotation(doneTime)")
    public Object around(ProceedingJoinPoint joinPoint, DoneTime doneTime) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object o = joinPoint.proceed();
        String str = "## DoneTime-" + joinPoint.getSignature() + ":" + (System.currentTimeMillis() - startTime);
        log.error(str);
        return o;
    }
}

      

这样我们就完成了两个非常典型的AOP切面的例子!

继续阅读