Spring中能否创建捕获log.info执行的pointcut?该做法是否属于良好实践?
问题解答
需求是否可实现
该需求可以实现,但你当前的写法在默认Spring AOP场景下无法生效,核心原因和实现前提如下:
- 首先你的示例代码本身存在语法问题:导入的是
org.aspectj.lang.annotation.Before注解,但实际使用了@After通知,直接运行会抛出编译异常 - Spring AOP仅支持对Spring容器托管的Bean的公共方法执行切入,而SLF4J的Logger实例通常是通过
LoggerFactory.getLogger(xxx)直接创建,不会交给Spring容器管理,因此默认情况下你写的切点根本匹配不到目标方法 - 要实现切入所有
log.info(...)调用的效果,需要改用全功能的AspectJ框架,选择编译时织入或者加载时织入的模式,才能对非Spring托管的SLF4J日志类方法完成切入
该实现是否属于行业良好实践
该方案不属于行业公认的良好实践,存在非常多的生产隐患:
- 性能损耗严重:所有日志调用都会额外执行切面逻辑,如果你的切面逻辑包含网络IO(比如将日志参数发往服务器),会大幅拖慢日志打印速度,甚至阻塞正常业务流程
- 死循环风险极高:如果切面内部或者网络请求的依赖代码中又打印了日志,会反复触发当前切面逻辑,直接引发栈溢出导致服务崩溃
- 可维护性差:切面直接侵入日志框架的底层调用,后续如果更换日志实现、升级SLF4J版本都可能导致切点失效,且日志相关的问题排查难度会大幅提升,很难第一时间定位到是AOP逻辑导致的异常
- 存在更标准的替代方案:如果需要采集日志上报到服务器,直接使用日志框架原生的扩展点即可,比如Logback自定义
Appender、Log4j2自定义Appender,这是日志框架预留的标准扩展能力,稳定性、兼容性远高于AOP切入方案
内容的提问来源于stack exchange,提问作者juanmorschrott
相关产品推荐
相关产品推荐

