自定义注解

自定义注解 @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,注入就会失败。
  • 可以通过为注解的属性设置默认值来支持不带参数的使用,但默认值可能会引起歧义,需要谨慎设计。
相关推荐
xzkyd outpaper40 分钟前
Kotlin 协程线程切换机制详解
android·开发语言·kotlin
啊森要自信1 小时前
【QT】常⽤控件详解(六)多元素控件 QListWidget && Table Widget && Tree Widget
c语言·开发语言·c++·qt
屁股割了还要学1 小时前
【数据结构入门】栈和队列
c语言·开发语言·数据结构·学习·算法·青少年编程
z樾1 小时前
MATLAB核心技巧:从入门到精通
开发语言·matlab
暗流者2 小时前
信息安全简要
开发语言·网络·php
苹果醋32 小时前
React Native jpush-react-native极光推送 iOS生产环境接收不到推送
java·运维·spring boot·mysql·nginx
老华带你飞2 小时前
数码论坛|基于SprinBoot+vue的数码论坛系统(源码+数据库+文档)
java·前端·数据库·vue.js·论文·毕设·数码论坛系统
葵野寺2 小时前
【JVM】深入解析Java虚拟机
java·linux·jvm·gc·垃圾回收
程序猿七度3 小时前
【FastExcel】解决ReadSheet在Map中获取对象不准确问题(已提交PR并合并到开源社区)
java·开源·fastexcel
绕灵儿3 小时前
C++ 部署LSTM(.onnx)
开发语言·c++·lstm