Spring 里那些“加了没生效”的注解

举报
yd_241780069 发表于 2026/11/01 18:35:51 2026/11/01
【摘要】 起因写代码的时候加了个注解,心里觉得稳了,跑起来发现压根没起作用。排查半天,原因五花八门:有的被同类调用绕过去了,有的被代理机制吃了,有的干脆得配合另一个注解才能用。这篇记几个我实际撞过的,都是“看着没问题、跑起来不对”的类型。 @Async 加了还是同步方法上标了 @Async,调用方等了半天,返回值也拿到了,怎么看都是同步执行的。两种常见原因。一种是同类调用。this.asyncMet...

起因

写代码的时候加了个注解,心里觉得稳了,跑起来发现压根没起作用。排查半天,原因五花八门:有的被同类调用绕过去了,有的被代理机制吃了,有的干脆得配合另一个注解才能用。

这篇记几个我实际撞过的,都是“看着没问题、跑起来不对”的类型。

@Async 加了还是同步

方法上标了 @Async,调用方等了半天,返回值也拿到了,怎么看都是同步执行的。

两种常见原因。

一种是同类调用。this.asyncMethod() 走的是原始对象,代理根本没参与,@Async 自然不生效。跟事务那个坑一模一样。

另一种是没开异步支持。没加 @EnableAsync 的话,@Async 就是个摆设,不报错,静默失效。这个最坑,因为代码看起来完全正常。

还有个小细节:@Async 方法如果返回 void,异常会被吞掉,日志里啥都看不到。想捕获异常,返回 Future 或者配 AsyncUncaughtExceptionHandler。我现在的写法是返回 CompletableFuture<Void>,至少出问题的时候能看出来。

@Valid 不校验

Controller 参数上加了 @Valid,传个空字段进来,居然不报错。

先查参数上有没有 @RequestBody。没有的话,@Valid 对表单参数和路径参数的处理方式不一样,得配合 @Validated 在类上标注。

再查实体类里的字段有没有约束注解。@Valid 本身不校验任何东西,它只是触发校验,真正干活的是 @NotNull、@Size 这些。字段上啥都没标,@Valid 加了也白加。

还有一种:嵌套对象里的字段不校验。比如 Order 里有个 User 字段,User 里的字段标了 @NotNull,但 Order 里这个字段没加 @Valid,嵌套校验就不会触发。得一层一层标下去,或者用 @Validated 在类级别配合分组校验。

@Transactional 的那个老问题

这个写太多次了,但每次遇到还是得愣一下。方法不是 public、异常被 catch、同类调用,三个里必中一个。

最近又加了一条:类上标了 @Transactional,方法上又标了一个传播行为不同的,结果以方法上的为准,类上的被覆盖。这个不算坑,但容易看漏,尤其是继承关系里父类标了、子类没标的情况。

@Cacheable 缓存不更新

查询方法上加了 @Cacheable,更新方法上加了 @CacheEvict,改完数据再查,还是旧值。

先确认 @EnableCaching 开了没有。没开的话注解全是装饰品,不报错。

再确认 key 是不是一致。@Cacheable 和 @CacheEvict 的 key 表达式如果写得不一样,清除的时候清的是另一个 key,原来的缓存纹丝不动。我见过一个 case,查询用默认 key(方法参数),清除用 #id,参数名一改就对不上了。

还有一个:同类调用。又是它。更新方法内部调了清除缓存的方法,走 this,代理没参与,@CacheEvict 不执行。

@ConfigurationProperties 注入不进来

配了个 @ConfigurationProperties(prefix = "app") 的类,字段全是 null。

最常见的原因是这个类没被 Spring 管理。要么加 @Component,要么在启动类上加 @EnableConfigurationProperties(MyProps.class),要么用 @ConfigurationPropertiesScan。光加 @ConfigurationProperties 不顶用,它只声明“我要绑配置”,不负责注册 Bean。

另一个原因是没有 setter。字段如果是 private 且只有 getter,Spring 绑不进去。用构造器绑定的话,得配合 @ConstructorBinding(Spring Boot 3 里不需要显式标了,单构造器自动识别)。

小结

这些注解失效的根子就两类:代理没参与(同类调用、非 public、没开开关),配置没到位(缺 @EnableXxx、缺配套注解、类没被管理)。

排查的时候我现在的顺序是:先确认开关开了没有,再看是不是同类调用,最后查注解之间的配合。三步走完,大部分“加了没生效”都能定位。

先记这些。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。