将学习的内容经过提炼后进行输出,加深理解和记忆!不能通过自己的话说出来的知识,就是没有学到位!
前言
本文记录使用Spring boot过程中关于自定义注解的理解和使用技巧。
一、什么是注解
自己的话:类似于商品上的标签,标注商品的信息。springboot相当于收银台,扫码枪扫一下标签就知道标注了这个标签的商品信息。
在 Spring Boot 中,注解(Annotations) 是一种元数据机制,它允许你在 Java 源代码中添加描述性信息,这些信息可以在编译时、运行时或部署时被处理和使用。Spring Boot 在 Spring 框架的基础上进行了封装,并提供了大量简化的注解(Starter Annotations),以减少配置的复杂性和样板代码。
注解本质上是 Java 提供的一种语法结构,可以附加在类、方法、变量、参数
等结构上,用来传递信息或指示编译器或运行时进行某些特殊操作。在 Spring Boot 应用中,注解广泛用于:
- 配置组件(如 bean 定义)
- 控制器映射(如 RESTful 路由)
- 数据访问(如 JPA、MyBatis 等注解)
- 自动装配依赖(如
@Autowired
) - 条件配置(如
@ConditionalOnMissingBean
) - 启动和生命周期管理(如
@SpringBootApplication
)
二、Spring Boot常用注解
1. Spring Boot 核心启动类注解
java
@SpringBootApplication
// 是 @SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan 的组合
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
2. 组件注册与注入
java
@Component
// 声明在类上,将其注入 Spring 容器为 bean
@Service
// 声明业务层 bean
@Repository
// 声明数据访问层 bean,并能捕获相关数据库异常
@Autowired
// 自动注入依赖,用在字段、构造方法、方法上等
3. 控制器和请求映射
java
@RestController
// 组合 @Controller 和 @ResponseBody(常用于 API 接口)
@RequestMapping("/api")
// 一般的请求映射
@GetMapping, @PostMapping, @PutMapping, @DeleteMapping
// HTTP 方法专用请求映射(GET、POST、PUT、DELETE)
@RequestBoody
// 将接收的json格式的数据转为java对象
// ps: 经常忘记标注导致输入对象为空......
4. 数据访问相关(JPA / Hibernate)
java
@Entity
// 声明一个类对应数据库表
@Id
@GeneratedValue
// 主键映射和生成策略
@Table(name = "myTableName)
// 对应数据库表名称
@Column(name = "username")
// 对应数据库字段
@OneToMany, @ManyToOne
// 映射实体之间的关系
5. 配置类与 Bean 定义
java
@Configuration
// 标明这是一个配置类(替代原来的 XML)
@Bean
// 在配置类方法上定义一个 bean,返回值交给 Spring 容器管理
@Value("${my.config.key}")
// 从配置文件注入简单值
@ConfigurationProperties
// 从配置文件绑定多个属性为一个类
6. 其他实用注解
java
@Valid
// 启用数据校验(结合 JSR-380 规范)
@Aspect
@Component
// 声明一个切面类,用在面向切面编程
@Transactional
// 声明事务边界
三、自定义注解
Java 的自定义注解本质是一个接口(可以理解为特殊形式的接口),声明方式如下:
java
@Documented
@Target(ElementType.TYPE) // 注解可使用在类上
@Retention(RetentionPolicy.RUNTIME) // 注解保存到运行时,可以通过反射获取
public @interface MyCustomAnnotation {
String value() default "default";
}
1. @Target
表明可以使用该注解的类型。
java
@Target({
ElementType.TYPE, // 可用于类、接口、枚举
ElementType.METHOD, // 可用于方法
ElementType.FIELD, // 可用于字段(成员变量)
ElementType.PARAMETER,// 可用于方法参数
ElementType.CONSTRUCTOR, // 构造器
ElementType.LOCAL_VARIABLE, // 局部变量
ElementType.ANNOTATION_TYPE, // 用于其它注解类(自定义 meta-annotation)
ElementType.PACKAGE, // 用于包声明
ElementType.TYPE_PARAMETER, // Java8+ 用于泛型参数
ElementType.TYPE_USE // Java8+ 用于任何类型使用(例如强制转换、new 等)
})
2. @Retention
设置注解保留在哪个阶段
值 | 说明 |
---|---|
RetentionPolicy.SOURCE | 注解仅保留在源代码中,不编译为 class 文件,如 @Override |
RetentionPolicy.CLASS | 注解存在于 .class 文件中,但运行时不可见(默认) |
RetentionPolicy.RUNTIME | 注解存在于运行时,可以通过反射 获取,这是大多数框架要用的保留策略 |
3. @Constraint
来自 javax.validation.constraints.Constraint 接口,定义在 javax.validation API 中(Java Bean Validation 标准的一部分)。
@Constraint 的主要作用是将你定义的校验注解(例如 @PasswordMatches)与一个实际的校验类(ConstraintValidator)进行绑定。
它允许你:
- 定义字段级别的规则(例如:字符串不能为 null;不能包含敏感词;字段A要等于字段B)
- 定义校验失败的提示信息
- 支持国际化(i18n)
- 在 Controller 中通过 @Valid 自动触发校验
使用语法:
java
@Documented
@Constraint(validatedBy = MyValidator.class)// 也可以指定多个@Constraint(validatedBy = { MyFirstValidator.class, MySecondValidator.class })
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface MyValidationRule {
String message() default "默认校验失败消息"; // 必须有,当校验失败时输出的提示信息,支持模板(如 `{min}`)
Class<?>[] groups() default {}; // 必须有,用于校验分组控制(可以指定在校验的某个阶段启用)
Class<? extends Payload>[] payload() default {}; // 必须有,可扩展用,如携带错误等级(INFO/WARN/FATAL)
// 你可以自定义参数,如字符串最小长度
int minLength() default 5;
}
使用方式
你需要提供一个类实现 ConstraintValidator<A extends Annotation, T>
接口:
A:自定义的注解
T:校验类接收的入参,注解用于字段,就是字段的类型;注解用于类,就是类名
java
public class MyFirstValidator implements ConstraintValidator<MyValidationRule, String> { // 用于MyValidationRule注解的地方。如果作用于某个vo类,就是<MyValidationRule, xxxVO>
private int minLength;
@Override
public void initialize(MyValidationRule constraintAnnotation) {
// 从注解中读取配置参数(如 min)
this.minLength = constraintAnnotation.minLength();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
// 校验逻辑:value 是使用注解字段的当前值
if (value == null || value.length() < minLength) {
return false;
}
return true;
}
}
四、 自定义校验实例
实现一个 @NotOnlyWhitespace
注解,用于校验字符串至少有一个非空格字符,而不仅仅是空格。
1. 定义注解
java
@Documented
@Constraint(validatedBy = NotOnlyWhitespaceValidator.class)
@Target({ ElementType.FIELD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface NotOnlyWhitespace {
String message() default "不能为空字符串或者仅包含空格"; // 默认消息
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
2. 实现校验器
java
public class NotOnlyWhitespaceValidator implements ConstraintValidator<NotOnlyWhitespace, String> {
@Override
public void initialize(NotOnlyWhitespace constraintAnnotation) {
// 初始化逻辑(可空)
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null || value.trim().isEmpty()) {
return false;
}
return true;
}
}
3. DTO 中使用
java
public class UserDTO {
@NotOnlyWhitespace(message = "用户名不能全为空格")
private String username;
// Getter/Setter
}
4. 启用校验
java
@PostMapping("/users")
public ResponseEntity<?> createUser(@Valid @RequestBody UserDTO userDTO) {
return ResponseEntity.ok("验证通过");
}
尾声
以上是个人是对自定义注解的一些理解和使用的经验,主要参考资料来源:Qwen3 235B A22B
,如有谬误,欢迎指正。