AOP
spring 的 AOP,Aspect Oriented Program 面向切面编程
通俗点说,一个切点,有上切面,有下切面,切点是一个函数
当需要函数执行的时候,会有这么个流程:上切面 -> 切点 -> 下切面
使用
1、添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2、编写Controller类
package com.example.demo3.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Controller
public class MyController {
//打印日志
private static final Logger logger = LoggerFactory.getLogger(MyController.class);
@GetMapping("hello")
@ResponseBody
public String Hello(){
logger.info("hello");
return "Hello";
}
}
3、编写AOP类
package com.example.demo3.aop;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class AOPTest {
//打印日志
private static final Logger logger = LoggerFactory.getLogger(AOPTest.class);
/**
* 定义一个切点
*/
@Pointcut(value = "execution(public String Hello (..))") //注意这里是全文件匹配函数
public void cutOffPoint() {
}
//上切面
@Before("cutOffPoint()")
public void beforeTest(){
logger.info("Hi !");
}
//下切面
@After("cutOffPoint()")
public void doAfter(){
logger.info("Bye !");
}
}
点击运行,打开浏览器输入 localhost:8080/hello
或者使用环绕@Around来代替@Before和@After
package com.example.demo3.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class AOPTest {
//打印日志
private static final Logger logger = LoggerFactory.getLogger(AOPTest.class);
/**
* 定义一个切点
*/
@Pointcut(value = "execution(public String Hello (..))") //注意这里是全文件匹配函数
public void cutOffPoint() {
}
@Around("cutOffPoint()")
public Object doAround(ProceedingJoinPoint pjp){
ThreadLocal<Long> startTime = new ThreadLocal<>();
startTime.set(System.currentTimeMillis());
logger.info("我是环绕通知执行");
Object obj;
try{
obj = pjp.proceed(); //启动目标方法执行
logger.info("执行返回值 : " + obj);
logger.info(pjp.getSignature().getName()+"方法执行耗时: " + (System.currentTimeMillis() - startTime.get()));
} catch (Throwable throwable) {
obj=throwable.toString();
}
return obj;
}
}
运行
@AfterReturning
切入点返回结果之后执行,也就是都前置后置环绕都执行完了,这个就执行了(PS:但实际上我自测的时候发现这个函数是比after要早执行的,不知道是哪里出问题了。。)
/**
* 执行完请求可以做的
* @param result
* @throws Throwable
*/
@AfterReturning(returning = "result", pointcut = "cutOffPoint()")
public void doAfterReturning(Object result) throws Throwable {
logger.info("大家好,我是@AfterReturning,他们都秀完了,该我上场了");
}
技巧
1、可以将注解作为切点,然后给需要Aop的函数标上注解即可
@Pointcut("@annotation(cn.itechyou.cms.annotation.Log)")
public void cutOffPoint() {}
参考博文: