自定义注解

自定义注解 @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,注入就会失败。
  • 可以通过为注解的属性设置默认值来支持不带参数的使用,但默认值可能会引起歧义,需要谨慎设计。
相关推荐
ChinaRainbowSea3 小时前
四.4 Redis 五大数据类型/结构的详细说明/详细使用( zset 有序集合数据类型详解和使用)
java·javascript·数据库·redis·后端·nosql
苏-言4 小时前
SSM框架探秘:Spring 整合 Mybatis 框架
java·spring·mybatis
qq_447663055 小时前
java-----多线程
java·开发语言
a辰龙a5 小时前
【Java报错解决】警告: 源发行版 11 需要目标发行版 11
java·开发语言
听海边涛声5 小时前
JDK长期支持版本(LTS)
java·开发语言
IpdataCloud5 小时前
Java 获取本机 IP 地址的方法
java·开发语言·tcp/ip
MyMyMing5 小时前
Java的输入和输出
java·开发语言
忆~遂愿5 小时前
3大关键点教你用Java和Spring Boot快速构建微服务架构:从零开发到高效服务注册与发现的逆袭之路
java·人工智能·spring boot·深度学习·机器学习·spring cloud·eureka
Easonmax5 小时前
【javaSE】内部类(来自类和对象的补充)
开发语言·javascript·ecmascript
云夏之末5 小时前
【Java报错已解决】java.lang.UnsatisfiedLinkError
java·开发语言