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

Spring获取方法自定义注解为null、isAnnotationPresent返回false问题

问题原因

Spring容器返回的@Repository标注类的实例默认是代理对象,并非原始业务类的实例:

  • 若使用JDK动态代理:代理类仅实现对应的业务接口,重写的方法不会携带原始实现类方法上的自定义注解
  • 若使用CGLIB代理:代理类是原始业务类的子类,方法级别的注解默认不会被子类继承,即使注解添加@Inherited元注解也仅对类级别注解生效,对方法级别注解无效

解决方法

方案1:使用Spring内置工具类处理代理场景(推荐)

直接用Spring封装的AopUtils和AnnotationUtils工具类,自动适配代理场景下的注解查找逻辑,修改扫描代码如下:

import org.springframework.aop.support.AopUtils;
import org.springframework.core.annotation.AnnotationUtils;

@Configuration
public class MyAnnotationScanner implements ApplicationContextAware {

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

        for (String beanName : applicationContext.getBeanNamesForAnnotation(Repository.class)) {
            Object bean = applicationContext.getBean(beanName);
            // 获取代理对应的原始业务类
            Class<?> targetClass = AopUtils.getTargetClass(bean);
            for (Method method : targetClass.getDeclaredMethods()) {
                MyAnnotation annotation = AnnotationUtils.findAnnotation(method, MyAnnotation.class);
                if (annotation != null) {
                    // 此处写入你的业务逻辑,可通过annotation.value()获取注解属性
                }
            }
        }
    }
}

方案2:注解迁移到接口方法

如果业务逻辑允许,将@MyAnnotation标注在接口Interface的doSomething方法上,代理类生成时会继承接口方法的注解,原有扫描逻辑无需修改也可以读取到注解。

方案3:手动拆解代理对象

如果不想依赖Spring的注解工具类,也可以先判断当前实例是否为代理,拆解出原始对象后再反射读取注解:

import org.springframework.aop.framework.Advised;
import org.springframework.aop.support.AopUtils;

if (AopUtils.isAopProxy(bean) && bean instanceof Advised) {
    bean = ((Advised) bean).getTargetSource().getTarget();
}
// 后续再执行原有的方法注解读取逻辑即可

该方案兼容性较差,部分特殊代理场景下可能无法获取到原始对象,仅作为备选方案使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 20:57:03