在Java中,用抽象类封装日志记录通用切面:将共性逻辑(如方法进入、返回、异常捕获)抽到@Aspect抽象类中,通过protected abstract钩子方法(如shouldLogMethod、buildLogMessage)由子类定制行为,配合@Pointcut和@Around实现统一环绕流程,子类仅需继承并实现关键抽象方法即可适配不同日志策略,同时注意显式注册为Spring Bean及避免静态Logger注入。

在 Java 中,用抽象类封装日志记录通用切面,核心思路是:**把日志切面的共性逻辑(如方法进入、返回、异常捕获)抽到抽象类中,由子类决定具体日志行为(比如是否打印参数、是否记录耗时、输出到哪)**。这样既复用 AOP 代码,又保留灵活性,避免每个切面重复写@Before/@After/@Around。
抽象日志切面基类设计
定义一个抽象类,用 @Aspect 标注,并声明通用的切入点和模板方法:
- 用 protected abstract 方法定义钩子(如
shouldLogMethod()、buildLogMessage()),让子类定制判断和内容 - 用 @Pointcut 定义默认切入点(如 controller/service 层方法),子类可重写
- 用 @Around 实现统一环绕逻辑:记录开始时间 → 执行目标 → 捕获结果或异常 → 调用抽象方法生成日志 → 输出
子类按需实现日志策略
继承抽象类后,只需覆盖关键抽象方法,不用重复写 AOP 注解和流程控制:
-
Controller 日志子类:重写
shouldLogMethod()只拦截@RestController方法;buildLogMessage()包含请求路径、入参 JSON、响应状态 -
Service 性能日志子类:重写
shouldLogMethod()拦截@Service的 public 方法;buildLogMessage()重点拼接耗时、方法名、参数摘要 - 可加
isDebugEnabled()判断,避免生产环境冗余日志
注意 Spring 上下文与代理问题
抽象切面类本身不会被 Spring 自动注册为 Bean,必须显式配置:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 子类需加 @Component(或 @Configuration + @Bean),确保被扫描到
- 若目标类未被 Spring 管理(如 new 出来的对象),切面不生效 —— 日志切面只对 Spring 代理对象有效
- 避免在抽象类中直接注入
Logger实例(如private static final Logger log = ...),应通过子类获取所属类名来初始化,保证日志来源清晰
简单示例片段
抽象类中 Around 逻辑示意:
@Around("logPointcut()")
public Object logExecution(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
String methodName = joinPoint.getSignature().toShortString();
if (!shouldLogMethod(joinPoint)) return joinPoint.proceed();
<pre class="brush:php;toolbar:false;">try {
Object result = joinPoint.proceed();
long cost = System.currentTimeMillis() - start;
log.info(buildLogMessage(joinPoint, result, cost, null));
return result;
} catch (Throwable e) {
long cost = System.currentTimeMillis() - start;
log.error(buildLogMessage(joinPoint, null, cost, e), e);
throw e;
}}
子类只需实现 buildLogMessage(),比如返回 "[Service] updateOrder: cost=123ms, input=id=123, error=null"。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










