如何使用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
相关产品推荐
相关产品推荐

