@target 不是校验注解,仅声明自定义注解的使用位置(如字段、参数、方法、类),真正校验由 @constraint + validatedby 指定的校验器执行;常见 elementtype 包括 field、parameter、method、type。

直接说重点:@Target 不是校验注解,它不参与任何数据校验逻辑,而是用来声明“这个自定义注解可以加在哪儿”——比如类、方法、字段、参数等。真正做校验的是 @Constraint + validatedBy 指向的校验器类。搞混 @Target 和校验行为,是新手最容易踩的坑。
明确 @Target 的作用范围
@Target 是 Java 元注解,只负责标注“使用位置”,不影响运行时校验。常见取值及适用场景:
- ElementType.FIELD:加在实体类字段上(如状态码、类型枚举)
- ElementType.PARAMETER:加在 Controller 方法参数上(适合简单单值校验,如 ID 格式)
- ElementType.METHOD:加在 Service 或 Mapper 方法上(常用于权限、数据范围等 AOP 场景)
- ElementType.TYPE:加在类上(如整个 DTO 需统一启用某类规则)
结合校验注解的典型组合写法
一个可用的自定义校验注解,必须同时包含 @Target 和 @Constraint,缺一不可。例如限制文章状态只能是“草稿”或“已发布”:
@Documented
@Constraint(validatedBy = StateValidator.class)
@Target({ ElementType.FIELD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface State {
String message() default "状态值非法";
Class>[] groups() default {};
Class extends Payload>[] payload() default {};
String[] value() default {"草稿", "已发布"};
}
注意:@Target 声明支持字段和参数,意味着你既能在 DTO 字段上用 @State,也能在接口方法形参上直接用,比如:public Result update(@State String state)
实际开发中容易出错的点
很多开发者写了校验逻辑,但接口始终不触发校验,问题往往出在 @Target 配置和使用位置不匹配:
- 注解标记了
@Target(ElementType.FIELD),却硬要写在方法参数上 → 不生效 - Controller 方法用了
@RequestBody UserDTO,但 DTO 字段没加校验注解,只在方法参数上加了@Valid→ 校验无对象可查 - 自定义注解漏了
@Constraint(validatedBy = ...)→ Spring 完全忽略该注解,当成普通标签
搭配 @Validated 实现精准控制
@Target 决定“能贴在哪”,而 @Validated 决定“什么时候校验”。两者配合才能闭环:
- DTO 字段加了
@State(其 @Target 包含 FIELD),Controller 方法参数需加@Validated或@Valid才会触发校验 - 若用分组校验(如 Create / Update 接口不同规则),@Target 不变,但 @Validated(Create.class) 会只校验对应分组的注解
- 方法级注解(如 @DataScope)配
@Target(METHOD),靠 AOP 切面拦截,不依赖 @Validated,但必须确保切面注册成功且方法被代理











