Spring Boot自定义注解

将学习的内容经过提炼后进行输出,加深理解和记忆!不能通过自己的话说出来的知识,就是没有学到位!

前言

本文记录使用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,如有谬误,欢迎指正。

相关推荐
xuxie139 小时前
SpringBoot文件下载(多文件以zip形式,单文件格式不变)
java·spring boot·后端
LiRuiJie10 小时前
深入剖析Spring Boot / Spring 应用中可自定义的扩展点
java·spring boot·spring
尚学教辅学习资料12 小时前
Ruoyi-vue-plus-5.x第五篇Spring框架核心技术:5.1 Spring Boot自动配置
vue.js·spring boot·spring
晚安里12 小时前
Spring 框架(IoC、AOP、Spring Boot) 的必会知识点汇总
java·spring boot·spring
上官浩仁13 小时前
springboot ioc 控制反转入门与实战
java·spring boot·spring
叫我阿柒啊14 小时前
从Java全栈到前端框架:一位程序员的实战之路
java·spring boot·微服务·消息队列·vue3·前端开发·后端开发
中国胖子风清扬14 小时前
Rust 序列化技术全解析:从基础到实战
开发语言·c++·spring boot·vscode·后端·中间件·rust
JosieBook18 小时前
【SpringBoot】21-Spring Boot中Web页面抽取公共页面的完整实践
前端·spring boot·python
刘一说19 小时前
Spring Boot+Nacos+MySQL微服务问题排查指南
spring boot·mysql·微服务
叫我阿柒啊1 天前
从Java全栈到云原生:一场技术深度对话
java·spring boot·docker·微服务·typescript·消息队列·vue3