You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Spring AOP与Log4j实现日志功能

如何用Spring AOP + Log4j实现日志功能?

看起来你已经搭好了Spring AOP切面的基础框架,不过我注意到你代码里用的是JDK自带的java.util.logging.Logger,这和你要用到的Log4j不是一个东西,先把这个小问题调整过来,然后一步步完善整个日志实现:

1. 先把依赖补全

首先得确保项目里引入了Spring AOP、AspectJ织入器以及Log4j的依赖。如果用Maven管理项目,把这些加到pom.xml里:

<!-- Spring AOP 核心依赖 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>5.3.20</version> <!-- 替换成你项目对应的Spring版本 -->
</dependency>
<!-- AspectJ 织入器,用来处理AOP切面 -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.7</version>
</dependency>
<!-- Log4j 日志核心包 -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
<!-- 推荐搭配SLF4J日志门面(可选,适配性更强) -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.36</version>
</dependency>

2. 修正切面类的Logger与日志逻辑

把你代码里的java.util.logging.Logger换成Log4j的Logger,然后完善各个通知方法的日志内容:

package com.loveTodo.springPractice.aspect;

import org.apache.log4j.Logger;
// 如果用SLF4J就换成下面两个导入
// import org.slf4j.Logger;
// import org.slf4j.LoggerFactory;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class CRMLoggingAspect {

    // 初始化Log4j Logger
    private Logger logger = Logger.getLogger(getClass());
    // SLF4J方式初始化:private Logger logger = LoggerFactory.getLogger(getClass());

    // 定义切入点:匹配你要拦截的方法,这里示例是service包下所有类的所有方法
    @Pointcut("execution(* com.loveTodo.springPractice.service.*.*(..))")
    private void serviceLayerMethods() {}

    // @Before通知:方法执行前记录调用信息
    @Before("serviceLayerMethods()")
    public void logBeforeMethod(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        logger.info("===== 准备执行方法:{},参数列表:{}", methodName, java.util.Arrays.toString(args));
    }

    // @AfterReturning通知:方法正常返回后记录返回结果
    @AfterReturning(pointcut = "serviceLayerMethods()", returning = "result")
    public void logAfterMethodReturn(JoinPoint joinPoint, Object result) {
        String methodName = joinPoint.getSignature().getName();
        logger.info("===== 方法:{} 执行完成,返回结果:{}", methodName, result);
    }

    // @AfterThrowing通知:方法抛出异常时记录异常详情
    @AfterThrowing(pointcut = "serviceLayerMethods()", throwing = "exception")
    public void logAfterMethodThrow(JoinPoint joinPoint, Throwable exception) {
        String methodName = joinPoint.getSignature().getName();
        logger.error("===== 方法:{} 执行抛出异常:{}", methodName, exception.getMessage(), exception);
    }
}

这里的切入点表达式可以根据你的需求调整,比如只拦截带特定注解的方法、特定返回值的方法,或者某个类的特定方法,灵活修改execution()里的规则就行。

3. 配置Log4j的输出规则

在src/main/resources下创建log4j.properties文件,配置日志的级别、输出位置和格式:

# 根日志级别:INFO及以上级别都会被记录
log4j.rootLogger=INFO, console, file

# 控制台输出配置
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
# 日志格式:时间 + 级别 + 类名 + 行号 + 日志内容
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

# 文件输出配置(可选,把日志写入文件)
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=logs/crm-app.log
log4j.appender.file.MaxFileSize=10MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

这个配置会把日志同时输出到控制台和logs/crm-app.log文件,文件超过10MB会自动分割,最多保留10个备份文件。

4. 开启Spring AOP自动代理

如果用注解配置Spring,在你的配置类上加上@EnableAspectJAutoProxy注解,开启AspectJ的自动代理功能:

package com.loveTodo.springPractice.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan("com.loveTodo.springPractice")
@EnableAspectJAutoProxy
public class AppConfig {
    // 其他配置项...
}

如果是XML配置方式,就加上这两行:

<aop:aspectj-autoproxy />
<context:component-scan base-package="com.loveTodo.springPractice" />

5. 测试验证

现在调用你service层的方法,就能在控制台或者日志文件里看到对应的日志了:

  • 方法执行前的INFO级调用日志
  • 方法正常返回后的INFO级结果日志
  • 如果方法抛出异常,会生成ERROR级的异常详情日志

你可以根据业务需求,再给日志加上更多信息,比如当前用户ID、请求ID等,让日志更有可读性。

内容的提问来源于stack exchange,提问作者bharath

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:13:09