业务场景:
如题:切面打印方法的执行时长等日志信息
实现流程:
-
引入jar包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
-
定义切面类
/***
* 切面输出方法调用的开始时间、结束时间等日志
*/
@Aspect
@Component
public class LogAspect {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
ObjectMapper objectMapper;
/***
* 第1个*代表任意返回类型
* ..代表service包及其子包
*第2个*代表任意类
*第3个*代表任意方法
* (..)表示任意数量的参数
*/
@Pointcut("execution(* com.example.demo..*.*(..))")
public void log() {
}
/***
* 前置通知:在某个连接点之前执行的通知,除非抛出一个异常,否则这个通知不能阻止连接点之前的执行流程
* @param joinPoint
*/
@Before("log()")
public void before(JoinPoint joinPoint) {
logger.info("方法{}执行前前,时间:{}", joinPoint.getSignature().toShortString(), new Date());
}
/***
* 环绕通知
* @param proceedingJoinPoint
*/
@Around("log()")
public void around(ProceedingJoinPoint proceedingJoinPoint) {
Date before = new Date();
logger.info("方法{}环绕通知前,时间:{}", proceedingJoinPoint.toShortString(), before);
try {
proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
logger.info("方法执行异常:{}", throwable.getMessage(), throwable);
}
Date after = new Date();
logger.info("方法{}环绕通知后,时间:{},方法执行时长:{}毫秒", proceedingJoinPoint.toShortString(), after, after.getTime() - before.getTime());
}
/***
* 执行完毕通知
* @param joinPoint
*/
@After("log()")
public void after(JoinPoint joinPoint) {
logger.info("方法{}执行完成通知,结束时间:{}", joinPoint.getSignature().toShortString(), new Date());
}
/***
* 方法返回通知
* @param joinPoint
*/
@AfterReturning("log()")
public void afterReturning(JoinPoint joinPoint) {
logger.info("方法{}返回通知,结束时间:{}", joinPoint.getSignature().toShortString(), new Date());
}
/***
* 方法抛出异常通知
* @param joinPoint
*/
@AfterThrowing("log()")
public void afterThrowing(JoinPoint joinPoint) {
logger.info("方法{}抛出异常通知,结束时间:{}", joinPoint.getSignature().toShortString(), new Date());
}
}
切入点的表达式中可以使用spring aop中支持的几种切入点指示符,Pointcut语法详解与示例
-
定义被切入类型
/***
* 集合测试、学习
*/
@Service
public class ListTestService {
private Logger logger = LoggerFactory.getLogger(this.getClass());
public void listSet(int cnt) {
List<String> list = new ArrayList<>();
for (int i = 0; i < cnt; i++) {
list.add(String.valueOf(i));
}
}
public void linkedListSet(int cnt) {
LinkedList<String> linkedList = new LinkedList<>();
for (int i = 0; i < cnt; i++) {
linkedList.add(String.valueOf(i));
}
}
}
-
单元测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
@Autowired
ListTestService learn;
@Test
public void learn1() {
learn.listSet(10000);
learn.linkedListSet(10000);
}
}
-
执行结果: