自定义注解

自定义注解 @MovieQualifier,它是基于 Spring 的 @Qualifier 注解之上的一个扩展。通过 元注解 和自定义属性(genre 和 format)来实现精确的依赖注入。


自定义注解的定义

@MovieQualifier 是一个 自定义的注解 ,它通过标注 @Qualifier 来继承了 @Qualifier 的功能,同时扩展了其能力。

java 复制代码
@Target({ElementType.FIELD, ElementType.PARAMETER}) // 允许注解作用于字段或参数
@Retention(RetentionPolicy.RUNTIME)  // 运行时保留此注解
@Qualifier // 声明这是一个扩展自 @Qualifier 的注解
public @interface MovieQualifier {
    String genre();   // 定义一个名为 "genre" 的属性
    Format format();  // 定义一个名为 "format" 的枚举类型属性
}
解读代码:
  1. @Target :定义了注解可以作用的范围。在这里,允许 @MovieQualifier 用于字段(FIELD)和参数(PARAMETER)。
  2. @Retention :定义了注解的生命周期。在这里,RUNTIME 表明注解在运行时仍然保留,可供反射使用。
  3. @Qualifier :继承了 Spring 的 @Qualifier 特性,使这个注解可以参与 Spring 的依赖注入流程。
  4. 自定义属性 :
    • genre:一个字符串,用于描述电影的类型(如 "Action"、"Comedy")。
    • format:一个枚举类型,用于描述电影的格式,比如是 2D、3D 等。

使用自定义 @MovieQualifier 的场景

我们可以用这个注解来标识特定的Bean,并在注入时通过提供对应的 genre 和 format 值来精确匹配。

示例:定义多个符合条件的Bean
java 复制代码
import org.springframework.stereotype.Component;

@Component
@MovieQualifier(genre = "Action", format = Format.DIGITAL)
public class ActionDigitalMovie implements Movie {
    // Bean 示例
}

@Component
@MovieQualifier(genre = "Comedy", format = Format.DVD)
public class ComedyDvdMovie implements Movie {
    // Bean 示例
}

在这里,我们定义了两个实现类 ActionDigitalMovie 和 ComedyDvdMovie,并通过 @MovieQualifier 注解分别标注了 genre 和 format 的属性值。


示例:使用 @MovieQualifier 进行注入
java 复制代码
public class MovieService {

    @Autowired
    @MovieQualifier(genre = "Action", format = Format.DIGITAL)
    private Movie actionMovie;

    @Autowired
    @MovieQualifier(genre = "Comedy", format = Format.DVD)
    private Movie comedyMovie;

    public void playMovies() {
        actionMovie.play();
        comedyMovie.play();
    }
}
运行时注入逻辑:
  1. Spring 会扫描到 @MovieQualifier 注解中的属性(如 genre = "Action" 和 format = Format.DIGITAL)。
  2. 通过这些属性值,Spring 在容器中查找标识为 @MovieQualifier(genre = "Action", format = Format.DIGITAL) 的Bean。
  3. 匹配成功后,将对应的 ActionDigitalMovie 注入到 actionMovie 字段中。

为什么可以不带参数?

实际上 @MovieQualifier 本身的属性(genre 和 format)就是用于自定义精确匹配规则的参数。如果你省略了这些属性值,Spring 无法匹配到具体的Bean,会导致注入失败。

错误示例
java 复制代码
@Autowired
@MovieQualifier // 没有参数,Spring 无法识别要注入的Bean
private Movie movie;

Spring 会抛出类似下面的异常:

复制代码
No qualifying bean of type 'Movie' available: expected single matching bean but found 2.

原因是 @MovieQualifier 的属性(genre 和 format)是注解的 必填项,你必须提供它们的值,否则 Spring 无法辨别要注入哪个Bean。


如何改进?

如果确实希望 @MovieQualifier 能够不带参数,可以为其属性定义默认值。但请注意,这可能导致歧义,因为默认值可能与多个Bean匹配。

示例:为属性提供默认值
java 复制代码
public @interface MovieQualifier {

    String genre() default "Action";  // 默认值为 "Action"
    Format format() default Format.DIGITAL;  // 默认值为 Format.DIGITAL
}
使用示例
java 复制代码
@Autowired
@MovieQualifier // 没有参数,默认使用 genre = "Action", format = Format.DIGITAL
private Movie movie;

总结

  • 自定义 @MovieQualifier 是 @Qualifier 的扩展版本,通过增加属性(如 genre 和 format),可以实现更精确的依赖注入。
  • 如果不带参数,Spring 无法通过 @MovieQualifier 的属性值匹配Bean,注入就会失败。
  • 可以通过为注解的属性设置默认值来支持不带参数的使用,但默认值可能会引起歧义,需要谨慎设计。
相关推荐
朝朝辞暮i7 小时前
C++ 第 29 课:回调函数 Callback
开发语言·c++·算法
FPGA小徐7 小时前
PA1 基础设施(2)深度解析:NEMU 中 ITRACE、MTRACE、FTRACE、IRINGBUF、ETRACE、DIFFTEST 全解析
java·服务器·网络
笨笨饿7 小时前
140_AI新手村MCP与Skills是干嘛的
开发语言·人工智能·python·stm32·单片机·嵌入式硬件·物联网
YOLO数据集集合7 小时前
EvoAgent:面向PR研发治理的自进化Multi-Agent Harness系统
java·开发语言·目标检测·agent·自进化
知行EDI8 小时前
知行之桥 MaBang 端口使用指南——Create Order 订单创建篇
java·服务器·数据库
笑鸿的学习笔记8 小时前
C++笔记之大块顺序写
java·c++·笔记
打工仔折腾 AI8 小时前
从 Demo 到生产级 Agent:8 个关键设计机制与 Python 实现拆解
java·jvm·人工智能·后端·python·langchain·ai agent 实战
殷色玫瑰9 小时前
C/C++ 内存管理详解:从内存分布到 new/delete 底层原理
java·linux·c语言·c++
知识分享小能手10 小时前
C++ 学习教程,从入门到精通,C++ 友元、异常和其他特性 — 详细知识点(15)
开发语言·c++·学习
青山木10 小时前
Hot 100 --- 编辑距离
java·数据结构·算法·leetcode·动态规划