【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring Boot 中的 AOP:实现日志记录与性能监控

答应我,这篇一定要看到最后~!

 <前文回顾>

点击此处查看 合集 https://blog.youkuaiyun.com/foyodesigner/category_12907601.html?fromshare=blogcolumn&sharetype=blogcolumn&sharerId=12907601&sharerefer=PC&sharesource=FoyoDesigner&sharefrom=from_link

<今日更新>

一、开篇整活儿

今儿个咱唠唠 Spring Boot 里头的 AOP(面向切面编程)。这玩意儿吧,说大不大,说小不小,整好了是锦上添花,整不好就是火上浇油。你要是刚入门,那可得悠着点儿,别一上来就整得自己“翻车”了。

二、AOP 是啥玩意儿?

AOP 是 Spring 里头的一个高级特性,用来在不修改原有代码的情况下,给程序动态添加功能。比如说,你可以用 AOP 来记录日志、监控性能、处理异常啥的。Spring Boot 里头默认就集成了这玩意儿,用起来贼方便。

1. AOP 的核心概念

AOP 里头有几个核心概念:切面(Aspect)、连接点(Join Point)、通知(Advice)、切点(Pointcut)。

  • 切面:就是你要添加的功能,比如说日志记录、性能监控啥的。
  • 连接点:就是程序执行过程中的某个点,比如说方法调用、异常抛出啥的。
  • 通知:就是切面在连接点执行的动作,比如说在方法调用前记录日志。
  • 切点:就是用来匹配连接点的表达式,比如说匹配某个包下的所有方法。

2. AOP 的通知类型

AOP 里头有五种通知类型:

  • 前置通知(Before):在连接点之前执行。
  • 后置通知(After):在连接点之后执行,不管连接点是否抛出异常。
  • 返回通知(AfterReturning):在连接点正常返回后执行。
  • 异常通知(AfterThrowing):在连接点抛出异常后执行。
  • 环绕通知(Around):在连接点前后都执行,可以控制连接点的执行。

三、用 AOP 实现日志记录

日志记录是 AOP 的经典应用场景。你可以用 AOP 来记录方法的调用信息,方便以后排查问题。

1. 定义切面

首先,你得定义一个切面,用 @Aspect 注解标记。

Java Code

@Aspect

@Component

public class LoggingAspect {

    private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);

}

这段代码里头,LoggingAspect 是一个切面,@Aspect 注解标记了这个类,@Component 注解让 Spring 管理这个类。

2. 定义切点

然后,你得定义一个切点,用 @Pointcut 注解标记。

Java Code

@Aspect

@Component

public class LoggingAspect {

    private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);

    @Pointcut("execution(* com.example.demo.service.*.*(..))")

    public void serviceMethods() {}

}

这段代码里头,serviceMethods 是一个切点,execution(* com.example.demo.service.*.*(..)) 表示匹配 com.example.demo.service 包下的所有方法。

3. 定义通知

最后,你得定义通知,用 @Before、@After、@AfterReturning、@AfterThrowing 或 @Around 注解标记。

Java Code

@Aspect

@Component

public class LoggingAspect {

    private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);

    @Pointcut("execution(* com.example.demo.service.*.*(..))")

    public void serviceMethods() {}

    @Before("serviceMethods()")

    public void logMethodCall(JoinPoint joinPoint) {

        logger.info("调用方法:{}", joinPoint.getSignature().getName());

    }

}

这段代码里头,logMethodCall 是一个前置通知,@Before 注解标记了这个方法,JoinPoint 参数用来获取连接点的信息。

四、用 AOP 实现性能监控

性能监控是 AOP 的另一个经典应用场景。你可以用 AOP 来记录方法的执行时间,方便以后优化性能。

1. 定义切面

首先,你得定义一个切面,用 @Aspect 注解标记。

Java Code

@Aspect

@Component

public class PerformanceAspect {

    private static final Logger logger = LoggerFactory.getLogger(PerformanceAspect.class);

}

这段代码里头,PerformanceAspect 是一个切面,@Aspect 注解标记了这个类,@Component 注解让 Spring 管理这个类。

2. 定义切点

然后,你得定义一个切点,用 @Pointcut 注解标记。

Java Code

@Aspect

@Component

public class PerformanceAspect {

    private static final Logger logger = LoggerFactory.getLogger(PerformanceAspect.class);

    @Pointcut("execution(* com.example.demo.service.*.*(..))")

    public void serviceMethods() {}

}

这段代码里头,serviceMethods 是一个切点,execution(* com.example.demo.service.*.*(..)) 表示匹配 com.example.demo.service 包下的所有方法。

3. 定义通知

最后,你得定义通知,用 @Around 注解标记。

Java Code

@Aspect

@Component

public class PerformanceAspect {

    private static final Logger logger = LoggerFactory.getLogger(PerformanceAspect.class);

    @Pointcut("execution(* com.example.demo.service.*.*(..))")

    public void serviceMethods() {}

    @Around("serviceMethods()")

    public Object measureMethodExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {

        long startTime = System.currentTimeMillis();

        Object result = joinPoint.proceed();

        long endTime = System.currentTimeMillis();

        logger.info("方法 {} 执行时间:{} 毫秒", joinPoint.getSignature().getName(), endTime - startTime);

        return result;

    }

}

这段代码里头,measureMethodExecutionTime 是一个环绕通知,@Around 注解标记了这个方法,ProceedingJoinPoint 参数用来控制连接点的执行。

五、AOP 的坑点

1. 切点表达式写错了

AOP 里头,切点表达式写错了,那通知就不起作用了。你要是写错了,那可得好好检查检查。

Java Code

@Pointcut("execution(* com.example.demo.service.*.*(..))") // 写错了

public void serviceMethods() {}

这段代码里头,execution 写错了,应该是 execution。

当然,写不好表达式,可以问AI啊。

2. 通知顺序不对

AOP 里头,通知顺序不对,那结果就不对了。你要是顺序不对,那可得好好调整调整。

Java Code

@Before("serviceMethods()")

public void logMethodCall(JoinPoint joinPoint) {

    logger.info("调用方法:{}", joinPoint.getSignature().getName());

}

@Around("serviceMethods()")

public Object measureMethodExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {

    long startTime = System.currentTimeMillis();

    Object result = joinPoint.proceed();

    long endTime = System.currentTimeMillis();

    logger.info("方法 {} 执行时间:{} 毫秒", joinPoint.getSignature().getName(), endTime - startTime);

    return result;

}

这段代码里头,logMethodCall 和 measureMethodExecutionTime 的顺序很重要。

3. 切面没被 Spring 管理

AOP 里头,切面没被 Spring 管理,那通知就不起作用了。你要是没被管理,那可得好好检查检查。

Java Code

@Aspect // 没加 @Component

public class LoggingAspect {

    private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);

    @Pointcut("execution(* com.example.demo.service.*.*(..))")

    public void serviceMethods() {}

    @Before("serviceMethods()")

    public void logMethodCall(JoinPoint joinPoint) {

        logger.info("调用方法:{}", joinPoint.getSignature().getName());

    }

}

这段代码里头,LoggingAspect 没加 @Component 注解,Spring 不会管理这个类。

、额外再说一点

对于大多数 Spring Boot 项目,如果你只是简单地使用 AOP 来实现日志记录、事务管理等功能,并且已经引入了 spring-boot-starter-aop 依赖,那么通常不需要显式地使用 @EnableAspectJAutoProxy 注解。Spring Boot 会自动为你处理相关的配置。

然而,如果你有特殊的需求,比如自定义代理创建策略或确保 AOP 支持被启用,那么你可以考虑显式地使用 @EnableAspectJAutoProxy 注解

专有名词解释

  1. AOP:面向切面编程,一种编程范式,用来在不修改原有代码的情况下,给程序动态添加功能。
  2. 切面:AOP 里头的一个概念,表示你要添加的功能。
  3. 连接点:AOP 里头的一个概念,表示程序执行过程中的某个点。
  4. 通知:AOP 里头的一个概念,表示切面在连接点执行的动作。
  5. 切点:AOP 里头的一个概念,表示用来匹配连接点的表达式。
  6. 前置通知:AOP 里头的一种通知类型,在连接点之前执行。
  7. 后置通知:AOP 里头的一种通知类型,在连接点之后执行。
  8. 返回通知:AOP 里头的一种通知类型,在连接点正常返回后执行。
  9. 异常通知:AOP 里头的一种通知类型,在连接点抛出异常后执行。
  10. 环绕通知:AOP 里头的一种通知类型,在连接点前后都执行。
  11. JoinPoint:AOP 里头的一个接口,用来获取连接点的信息。
  12. ProceedingJoinPoint:AOP 里头的一个接口,用来控制连接点的执行。

写在最后

身为一个中古程序猿,我有很多自己想做的事情,比如埋头苦干手搓一个低代码数据库设计平台(目前只针对写java的朋友),已经在找朋友内测了,比如很喜欢帮身边的朋友看看简历,讲讲面试技巧,毕竟工作这么多年,也做到过高管,有很多面人经历,意见还算有用,大家基本都能拿到想要的offer...

我深刻意识到,能自由做自己喜欢的事情是有多么不容易,又是多么有成就感。所以我拉了两三个志同道合的好友,开了一间公司,继续朝着“自由”的目标前进。

当下呢,我们希望有更多的朋友能够参与到产品的测试中来,体验并且给出更好的建议。未来可能会在博客po更多关于我们产品的内容,包括使用场景、说明、课程等,希望能对大家有所帮助。

另外,想整个花活儿,每天花个1-2小时,来帮助我素未谋面的老朋友们看看简历,提提意见啥的,纯属为爱发电。我在线时间不固定,但是不要米,咱就别要自行车儿了呗~如果您有兴趣,可以点击文章底部卡片一起交流(人工回复,比较慢,请担待)

最后,请大家持续关注我们的博客,未来还有很多栏目,一起发掘~!

(来呀~↓↓↓↓↓↓↓↓老铁~)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值