Spring AOP切面未触发问题排查与解决
解决Spring AOP切面未触发问题
问题现象
预期切面生效时,日志应包含切面输出:
Sep 27, 2020 1:11:11 PM aspects.LoggingAspect log INFO: Method will execute Sep 27, 2020 1:11:11 PM com.cms.services.CommentService publishComment INFO: Publishing comment:Demo comment Sep 27, 2020 1:11:11 PM aspects.LoggingAspect log INFO: Method executed
但实际仅输出业务日志,切面完全未触发:
com.cms.services.CommentService publishComment INFO: Publishing Comment: Demo Comment
代码与环境
项目通过Main.java加载Spring上下文调用CommentService.java,CommentService位于services包下;LoggingAspect.java实现切面逻辑;CommentConfig.java配置@EnableAspectJAutoProxy并注册切面Bean。
Main.java
public class Main { public static void main(String[] args) { var c = new AnnotationConfigApplicationContext(CommentConfig.class); var service = c.getBean(CommentService.class); Comment comment = new Comment(); comment.setText("Demo Comment"); comment.setAuthor("Natasha"); service.publishComment(comment); } }
CommentService.java
@Service public class CommentService { private Logger logger = Logger.getLogger(CommentService.class.getName()); public void publishComment(Comment comment) { logger.info("Publishing Comment: " + comment.getText()); } }
原LoggingAspect.java
@Aspect @Component public class LoggingAspect { private Logger logger = Logger.getLogger(LoggingAspect.class.getName()); @Around("execution(* services.*.*(..))") public void log(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("method will execute"); logger.info("Method will execute"); joinPoint.proceed(); logger.info("Method has executed"); System.out.println("method has executed"); } }
CommentConfig.java
@Configuration @ComponentScan(basePackages = {"com.cms"}) @EnableAspectJAutoProxy public class CommentConfig { @Bean public LoggingAspect aspect() { return new LoggingAspect(); } }
依赖配置
<properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- Spring Context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.23</version> </dependency> <!-- Spring Aspects --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.3.23</version> </dependency> <!-- Spring AOP --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.3.24</version> </dependency> </dependencies>
包结构
├─src │ ├─main │ │ ├─java │ │ │ └─com │ │ │ └─cms │ │ │ │ Main.java │ │ │ │ │ │ │ ├─aspect │ │ │ │ LoggingAspect.java │ │ │ │ │ │ │ ├─config │ │ │ │ CommentConfig.java │ │ │ │ │ │ │ ├─model │ │ │ │ Comment.java │ │ │ │ │ │ │ ├─proxies │ │ │ │ CommentNotificationProxy.java │ │ │ │ CommentPushNotificationProxyImpl.java │ │ │ │ EmailCommentNotificationProxyImpl.java │ │ │ │ │ │ │ ├─repositories │ │ │ │ CommentRepository.java │ │ │ │ DBCommentRepositoryImpl.java │ │ │ │ │ │ │ └─services │ │ │ CommentService.java │ │ │ │ │ └─resources
问题原因
切面未触发的核心原因是@Around注解的execution切点表达式遗漏了完整包名。原表达式execution(* services.*.*(..))仅匹配根路径下的services包,而实际CommentService位于com.cms.services包下,导致切点无法匹配目标方法。
修复方案
修改LoggingAspect.java中的切点表达式,补充完整包路径com.cms.services,同时修正@Around方法的返回值类型(需返回Object并返回joinPoint.proceed()的结果,确保方法正常执行):
@Aspect @Component public class LoggingAspect { private Logger logger = Logger.getLogger(LoggingAspect.class.getName()); @Around("execution(* com.cms.services.*.*(..))") // 修正点:补充完整包名 public Object log(ProceedingJoinPoint joinPoint) throws Throwable { String methodName = joinPoint.getSignature().getName(); Object arguments[] = joinPoint.getArgs(); logger.info("Method " + methodName + " with Parameters " + Arrays.asList(arguments) + " will execute"); Object returnedByMethod = joinPoint.proceed(); logger.info("Method executed and returned " + returnedByMethod); return returnedByMethod; } }
参考建议
建议学习Spring官方文档中关于AspectJ切点表达式的语法规则,确保切点路径匹配准确。
内容的提问来源于stack exchange,提问作者mchun
相关产品推荐
相关产品推荐

