自定义注解

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


自定义注解的定义

@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,并在注入时通过提供对应的 genreformat 值来精确匹配。

示例:定义多个符合条件的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 示例
}

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


示例:使用 @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 本身的属性(genreformat)就是用于自定义精确匹配规则的参数。如果你省略了这些属性值,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 的属性(genreformat)是注解的 必填项,你必须提供它们的值,否则 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 的扩展版本,通过增加属性(如 genreformat),可以实现更精确的依赖注入。
  • 如果不带参数,Spring 无法通过 @MovieQualifier 的属性值匹配Bean,注入就会失败。
  • 可以通过为注解的属性设置默认值来支持不带参数的使用,但默认值可能会引起歧义,需要谨慎设计。
相关推荐
evans在进步9 小时前
LeetCode 17:电话号码的字母组合——Java DFS 回溯法详解
java·leetcode·深度优先
2401_850481179 小时前
UVA10391
java
UQR9 小时前
一、Java基础高频面试题
java·开发语言
AC赳赳老秦9 小时前
网页公开附件自动采集:OpenClaw 批量下载页面内嵌 Word/Excel 附件,统一格式后结构化入库
java·python·word·php·excel·deepseek·openclaw
MoonBit月兔9 小时前
MoonBit 受邀亮相 SPLASH/ISSTA 2026,与 Java、Rust、Eiffel、D 语言核心贡献者同场交流
开发语言·后端·rust
上海云盾商务经理杨杨9 小时前
Tomcat 弱配置漏洞渗透实战!批量 getshell 高频漏洞
java·web安全·tomcat
必须会一定会9 小时前
用纯 HTML/JS 做一个 AI 需求澄清器:把模糊想法转换成可执行任务书
开发语言·前端·javascript·人工智能·html·ai编程
10mAh9 小时前
【Linux】error while loading shared libraries 怎么解决?——ldd、RPATH 与动态链接排错
java·linux·前端
深念Y9 小时前
stable-diffusion.cpp 的 FLUX.2 Klein 9B 分步
java·前端·数据库
阿pin9 小时前
Java随笔-红黑树
java·python·算法·红黑树