很多时候我们需要在原有代码基础上对代码进行日志输出权限管控等可以使用aop技术,在不改变原来带有代码基础上进行操作
因为是springboot项目所以不需要写配置文件直接新建一个类,给类加上@Aspect注解 这个类就相当于一个切面类了
在编写切面类的前提是需要在pom.xml中引入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
<!-- SpringBoot 拦截器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
下面是切面类代码:类中有前置通知方法,后置通知方法,环绕通知等方法
package com.example.demo.aop;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import sun.rmi.runtime.Log;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
/**
* 对springboot中aop切面编程的测试
*/
//切面类
@Aspect
@Component
@Slf4j
public class AopAspect {
private Logger logger = LoggerFactory.getLogger(AopAspect.class);
Long timeStart;
Long timeEnd;
/***
* 定义切入点
*/
@Pointcut("execution(* com.example.demo.controller..*.*(..))")
public void pointCut(){
}
/**
* 前置增强:目标方法执行之前执行
*
* @param jp
*/
// @Before("pointCut()") // 所有controller包下面的所有方法的所有参数
public void beforeMethod(JoinPoint jp) {
timeStart = System.currentTimeMillis();
String methodName = jp.getSignature().getName();
log.info("【前置增强】the method 【" + methodName + "】 ");
}
/**
* 后置增强:目标方法执行之后执行以下方法体的内容,不管是否发生异常。
*
* @param jp
*/
// @After("pointCut()")
public void afterMethod(JoinPoint jp) {
log.info("【后置增强】this is a afterMethod advice...");
timeEnd = System.currentTimeMillis();
float time = (float) ((timeEnd - timeStart)/1000);
log.info("查询方法执行了---"+time+"-----");
}
/**
* 返回增强:目标方法正常执行完毕时执行
*
* @param jp
* @param result
*/
// @AfterReturning(value = "pointCut()", returning = "result")
public void afterReturningMethod(JoinPoint jp, Object result) {
String methodName = jp.getSignature().getName();
log.info("【返回增强】the method 【" + methodName + "】 ends with 【" + result + "】");
}
/**
* 异常增强:目标方法发生异常的时候执行,第二个参数表示补货异常的类型
*
* @param jp
* @param e
*/
// @AfterThrowing(value = "pointCut()", throwing = "e")
public void afterThorwingMethod(JoinPoint jp, Exception e) {
String methodName = jp.getSignature().getName();
log.error("【异常增强】the method 【" + methodName + "】 occurs exception: ", e);
}
/**
* 环绕增强:目标方法执行前后分别执行一些代码,发生异常的时候执行另外一些代码
*
* @return
*/
@Around(value = "pointCut()")
public Object aroundMethod(ProceedingJoinPoint jp) {
String methodName = jp.getSignature().getName();
Object result = null;
try {
log.info("【环绕增强中的--->前置增强】:the method 【" + methodName + "】 begins with " + Arrays.asList(jp.getArgs())+"执行开始时间+"+System.currentTimeMillis());
timeStart =System.currentTimeMillis();
//执行目标方法
result = jp.proceed();
timeEnd= System.currentTimeMillis();
log.info("【环绕增强中的--->返回增强】:the method 【" + methodName + "】 ends with " + result +"执行完的时间 "+System.currentTimeMillis());
} catch (Throwable e) {
result = "error";
log.info("【环绕增强中的--->异常增强】:the method 【" + methodName + "】 occurs exception " + e);
}
log.info("【环绕增强中的--->后置增强】:-----------------end.----------------------");
int time = (int) ((timeEnd - timeStart)/1000);
log.info("方法执行时间---"+time+"秒------");
return result;
}
}
其中pointCut方法是切入点,execution(* com.example.demo.controller..*.*(..))是需要进行操作方法的包名,我这里是对controller包下面所有的方法进行管控,如果是想对某个方法进行操作,可以研究一下AOP的execution表达式