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

Spring Boot 2.1显式注册TimedAspect后@Timed注解仍不生效

问题根源:Spring AOP的内部调用限制

你碰到的这个问题其实是Spring AOP的常见“坑”——当同一个类内部的方法互相调用时,不会经过Spring生成的代理对象,所以TimedAspect的切面逻辑根本没机会执行。

具体到你的代码里:ExampleUtil的sayhellowithtimed方法调用了自己的sayhello方法(也就是那个标注了@Timed的实现),这是直接通过this引用调用的目标对象方法,完全绕开了代理,自然不会触发指标统计。

可行的解决方案

下面给你几个不同的解决思路,你可以根据自己的代码结构选最顺手的:

1. 暴露代理对象,通过AopContext调用

这个方法改动最小,只需要两步:

第一步:开启代理暴露

在你的启动类ExampleStarter上,给@EnableAspectJAutoProxy加上exposeProxy = true:

@EnableAspectJAutoProxy(exposeProxy = true) // 关键:让Spring暴露代理对象
@ComponentScan
@Configuration
@SpringBootApplication
public class ExampleStarter{
    // 原有代码保持不变
}

第二步:修改内部调用逻辑

在AbstractUtil的sayhellowithtimed方法里,用AopContext获取当前代理对象,再调用sayhello:

import org.springframework.aop.framework.AopContext;

public abstract class AbstractUtil {
    public abstract void sayhello();
    
    public void sayhellowithtimed(String passedVar) {
        System.out.println("Passed var =>"+passedVar);
        System.out.println("Calling abstract sayhello....");
        // 换成通过代理对象调用,这样就能触发TimedAspect了
        ((AbstractUtil) AopContext.currentProxy()).sayhello();
    }
}

2. 自注入代理对象

在ExampleUtil里注入自身的代理对象,然后用这个代理来调用sayhello:

@Component
@Scope("prototype")
public class ExampleUtil extends AbstractUtil {
    public static final String HELLO = "HELLO";
    
    @Autowired
    private ExampleUtil selfProxy; // 注入自己的代理实例

    // 原有方法不变...

    @Override
    public void sayhellowithtimed(String passedVar) {
        System.out.println("Passed var =>"+passedVar);
        System.out.println("Calling abstract sayhello....");
        selfProxy.sayhello(); // 用代理对象调用,触发切面
    }
}

不用担心原型作用域的问题,Spring会正确给每个原型实例注入对应的代理对象。

3. 重构代码,把调用移到外部

如果不想碰AOP相关的配置,可以把sayhellowithtimed的逻辑抽出来放到另一个Spring组件里,比如在StartDirWatcher里直接调用util.sayhello(),或者新建一个专门的服务类来处理这个调用逻辑——只要是外部组件调用ExampleUtil的方法,就会经过代理,自然能触发@Timed统计。

4. 改用AspectJ织入(零业务代码修改)

如果完全不想改业务代码,可以用AspectJ的加载时或编译时织入,它能拦截所有方法调用(包括内部调用)。

第一步:添加AspectJ依赖

在pom.xml里加上:

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.9.6</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.6</version>
</dependency>

第二步:开启加载时织入

把启动类的@EnableAspectJAutoProxy换成@EnableLoadTimeWeaving,或者配置Maven编译插件实现编译时织入。

验证方法

改完之后,触发一次目录变更事件,然后访问/prometheus或/metrics端点,就能看到say_hello_example相关的指标了(比如say_hello_example_seconds_count、say_hello_example_seconds_sum这些)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:09:50