AspectJ中@Around无法拦截注解标注方法的问题求助
嘿,我来帮你捋清楚为啥你的执行时间记录切面没生效~核心问题其实很明确:你那个加了@LogExecutionTime注解的方法所属的类,没有被Spring容器管理。Spring AOP的底层是基于代理实现的,只有被Spring托管的Bean,Spring才能为它生成代理对象,进而触发你的切面逻辑。
下面是具体的解决步骤和需要注意的点:
1. 给目标类添加Spring组件注解
给execute()方法所在的类加上@Component(或者根据业务场景用@Service、@Repository这类更贴合的注解),比如:
@Component public class YourBusinessClass { @LogExecutionTime public void execute() throws Exception { // 你的业务逻辑代码 } }
这样Spring启动时会自动把这个类实例化为容器里的Bean,后续调用这个Bean的方法时,代理机制就能生效了。
2. 必须通过Spring容器获取Bean来调用方法
别再用new YourBusinessClass()这种方式手动创建对象了!这种方式创建的对象不在Spring容器的管控范围内,Spring没办法给它生成代理,切面自然不会触发。你得通过Spring的依赖注入来获取Bean,比如:
// 在任意Spring管理的类(比如Controller、Service)中注入目标Bean @Autowired private YourBusinessClass businessClass; // 调用方法 businessClass.execute();
3. 确认现有配置的正确性(你已经做了,但再核对下)
- 你的切面类
PerformanceAnnotation已经加了@Aspect和@Component,这没问题,Spring才能扫描到这个切面并把它加入容器。 - 主类上的
@EnableAspectJAutoProxy注解也加对了,这是开启Spring AOP自动代理的关键开关。 spring-boot-starter-aop依赖已经引入pom,确保版本和你的Spring Boot版本兼容就行。
额外的小提醒
如果你的execute()方法是private或者final修饰的,Spring AOP也没法拦截——因为JDK动态代理(基于接口)和CGLIB代理(基于类)都处理不了这类方法。不过看你的代码,方法是public的,这个坑你应该没踩。
另外,你的切面方法返回值是void,如果以后被拦截的方法有返回值,记得修改切面方法的返回值为Object,并返回joinPoint.proceed()的结果,不然调用方拿不到返回值哦:
@Around("@annotation(LogExecutionTime)") public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { Logger logger = getClassLogger(joinPoint); logger.info("Started method " + joinPoint.getSignature().getName() + " of class " + joinPoint.getTarget().getClass()); long start = System.currentTimeMillis(); Object result = joinPoint.proceed(); // 保存方法返回结果 long executionTime = System.currentTimeMillis() - start; logger.info("Execution time (millis): " + executionTime); return result; // 把结果返回给调用方 }
按上面的步骤调整后,再调用execute()方法,你的执行时间日志应该就能正常打印啦~
内容的提问来源于stack exchange,提问作者S-Wing

