原文: http://zetcode.com/springboot/qualifier/

Spring Boot @Qualifier教程展示了如何使用@Qualifier来区分相同类型的 bean。 它也可以用于注解其他自定义注解,这些注解随后可以用作限定符。

Spring 是流行的 Java 应用框架,而 Spring Boot 是 Spring 的演进,可帮助您以最少的精力创建独立的,生产级的基于 Spring 的应用。

以下三个应用是命令行 Spring Boot 应用。

@Qualifier Person bean

在我们的应用中,我们有两个Person类型的 bean:StudentManager。 我们使用@Qualifier注解来区分它们。

  1. pom.xml
  2. src
  3. ├───main
  4. ├───java
  5. └───com
  6. └───zetcode
  7. Application.java
  8. MyRunner.java
  9. └───model
  10. Manager.java
  11. Person.java
  12. Student.java
  13. └───resources
  14. └───test
  15. └───java

这是 Spring Boot 应用的项目结构。

pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  5. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  6. <modelVersion>4.0.0</modelVersion>
  7. <groupId>com.zetcode</groupId>
  8. <artifactId>springbootqualifier</artifactId>
  9. <version>1.0-SNAPSHOT</version>
  10. <packaging>jar</packaging>
  11. <properties>
  12. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  13. <maven.compiler.source>11</maven.compiler.source>
  14. <maven.compiler.target>11</maven.compiler.target>
  15. </properties>
  16. <parent>
  17. <groupId>org.springframework.boot</groupId>
  18. <artifactId>spring-boot-starter-parent</artifactId>
  19. <version>2.1.5.RELEASE</version>
  20. </parent>
  21. <dependencies>
  22. <dependency>
  23. <groupId>org.springframework.boot</groupId>
  24. <artifactId>spring-boot-starter</artifactId>
  25. </dependency>
  26. </dependencies>
  27. <build>
  28. <plugins>
  29. <plugin>
  30. <groupId>org.springframework.boot</groupId>
  31. <artifactId>spring-boot-maven-plugin</artifactId>
  32. </plugin>
  33. </plugins>
  34. </build>
  35. </project>

这是 Maven 构建文件。 spring-boot-starter是包括自动配置支持,日志记录和 YAML 在内的核心启动器。 该应用打包到一个 JAR 文件中。

com/zetcode/model/Person.java

  1. package com.zetcode.model;
  2. public interface Person {
  3. String info();
  4. }

我们有一个定义Person类型的接口。

com/zetcode/model/Student.java

  1. package com.zetcode.model;
  2. import org.springframework.beans.factory.annotation.Qualifier;
  3. import org.springframework.stereotype.Component;
  4. @Component
  5. @Qualifier("student")
  6. public class Student implements Person {
  7. @Override
  8. public String info() {
  9. return "Student";
  10. }
  11. }

Student继承自Person@Component是基本的 Spring 注解,它允许 Spring 容器检测Student@Qualifier("student")"student"字符串唯一标识此 bean。

com/zetcode/model/Manager.java

  1. package com.zetcode.model;
  2. import org.springframework.beans.factory.annotation.Qualifier;
  3. import org.springframework.stereotype.Component;
  4. @Component
  5. @Qualifier("manager")
  6. public class Manager implements Person {
  7. @Override
  8. public String info() {
  9. return "Manager";
  10. }
  11. }

我们还有另一个名为Manager的 bean。 该 bean 也用@Qualifier("manager")注解标识。

com/zetcode/MyRunner.java

  1. package com.zetcode;
  2. import com.zetcode.model.Person;
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.beans.factory.annotation.Qualifier;
  7. import org.springframework.boot.CommandLineRunner;
  8. import org.springframework.stereotype.Component;
  9. @Component
  10. public class MyRunner implements CommandLineRunner {
  11. private static final Logger logger = LoggerFactory.getLogger(MyRunner.class);
  12. @Autowired
  13. @Qualifier("student")
  14. private Person p1;
  15. @Autowired
  16. @Qualifier("manager")
  17. private Person p2;
  18. @Override
  19. public void run(String... args) throws Exception {
  20. logger.info("{}", p1.info());
  21. logger.info("{}", p2.info());
  22. }
  23. }

CommandLineRunner接口指示当SpringApplication中包含 bean 时应运行它。 它可以用来在 Spring Boot 中创建命令行应用。

  1. @Component
  2. public class MyRunner implements CommandLineRunner {

CommandLineRunner也是一个 Spring bean,并用@Component注解装饰。 它由 Spring 自动检测。

  1. @Autowired
  2. @Qualifier("student")
  3. private Person p1;

我们将Person bean 注入p1字段。 @Qualifier("student")指定它是一个Student bean。

  1. @Autowired
  2. @Qualifier("manager")
  3. private Person p2;

同样,我们将Manager bean 注入p2字段。

com/zetcode/Application.java

  1. package com.zetcode;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. @SpringBootApplication
  5. public class Application {
  6. public static void main(String[] args) {
  7. SpringApplication.run(Application.class, args);
  8. }
  9. }

Application设置 Spring Boot 应用。 @SpringBootApplication注解启用自动配置和组件扫描。

使用工厂创建 bean

在第二个应用中,我们使用工厂类来生成 bean。 pom.xmlPerson.javaApplication.javaMyRunner.java保持不变。

  1. pom.xml
  2. src
  3. ├───main
  4. ├───java
  5. └───com
  6. └───zetcode
  7. Application.java
  8. MyRunner.java
  9. ├───conf
  10. PersonFactory.java
  11. └───model
  12. Manager.java
  13. Person.java
  14. Student.java
  15. └───resources
  16. └───test
  17. └───java

这是项目结构。

com/zetcode/model/Manager.java

  1. package com.zetcode.model;
  2. public class Manager implements Person {
  3. @Override
  4. public String info() {
  5. return "Manager";
  6. }
  7. }

注解已从Manager类中删除。

com/zetcode/model/Student.java

  1. package com.zetcode.model;
  2. public class Student implements Person {
  3. @Override
  4. public String info() {
  5. return "Student";
  6. }
  7. }

同样,Student类没有注解。

com/zetcode/conf/PersonFactory.java

  1. package com.zetcode.conf;
  2. import com.zetcode.model.Manager;
  3. import com.zetcode.model.Person;
  4. import com.zetcode.model.Student;
  5. import org.springframework.beans.factory.annotation.Qualifier;
  6. import org.springframework.context.annotation.Bean;
  7. import org.springframework.context.annotation.Configuration;
  8. @Configuration
  9. public class PersonFactory {
  10. @Bean
  11. @Qualifier("student")
  12. public Person createStudent() {
  13. return new Student();
  14. }
  15. @Bean
  16. @Qualifier("manager")
  17. public Person createManager() {
  18. return new Manager();
  19. }
  20. }

在前面的示例中,Spring 会自动检测到这些 bean。 在这里,PersonFactory借助@Bean注解创建了两个 bean。

  1. @Bean
  2. @Qualifier("student")
  3. public Person createStudent() {
  4. return new Student();
  5. }

@Bean注解标记了定义 bean 的方法。 @Qualifier("student")指示要创建Person的哪个实现。

创建自定义@Qualifier注解

为了减少代码,我们可以创建自定义@Qualifier注解。

  1. pom.xml
  2. src
  3. ├───main
  4. ├───java
  5. └───com
  6. └───zetcode
  7. Application.java
  8. MyRunner.java
  9. ├───conf
  10. PersonFactory.java
  11. ├───model
  12. Manager.java
  13. Person.java
  14. Student.java
  15. └───qualifier
  16. PersonQ.java
  17. └───resources
  18. └───test
  19. └───java

这是项目结构; 我们列出了第一个应用中列出的pom.xml以外的所有文件。

com/zetcode/model/Person.java

  1. package com.zetcode.model;
  2. public interface Person {
  3. String info();
  4. }

这是Person类型。

com/zetcode/model/Manager.java

  1. package com.zetcode.model;
  2. import org.springframework.stereotype.Component;
  3. @Component
  4. public class Manager implements Person {
  5. @Override
  6. public String info() {
  7. return "Manager";
  8. }
  9. }

Manager类装饰有@Component注解; 它将由 Spring 自动检测。

com/zetcode/model/Student.java

  1. package com.zetcode.model;
  2. import org.springframework.stereotype.Component;
  3. @Component
  4. public class Student implements Person {
  5. @Override
  6. public String info() {
  7. return "Student";
  8. }
  9. }

Student的情况相同。

com/zetcode/qualifier/PersonQ.java

  1. package com.zetcode.qualifier;
  2. import java.lang.annotation.ElementType;
  3. import java.lang.annotation.Retention;
  4. import java.lang.annotation.RetentionPolicy;
  5. import java.lang.annotation.Target;
  6. import org.springframework.beans.factory.annotation.Qualifier;
  7. @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
  8. @Retention(RetentionPolicy.RUNTIME)
  9. @Qualifier
  10. public @interface PersonQ {
  11. String value();
  12. }

在这里,我们定义了一个新的@PersonQ限定符。

  1. @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})

@Targer注解指出可以在何处应用注解。 在我们的情况下,它可以应用于字段,方法和参数。

  1. @Retention(RetentionPolicy.RUNTIME)

@Retention注解指定标记的注解的存储方式。 使用RetentionPolicy.RUNTIME,标记的注解将由 JVM 保留,因此可以由运行时环境使用。

  1. public @interface PersonQ {

@interface关键字用于声明新的注解类型。

com/zetcode/conf/PersonFactory.java

  1. package com.zetcode.conf;
  2. import com.zetcode.model.Manager;
  3. import com.zetcode.model.Person;
  4. import com.zetcode.model.Student;
  5. import com.zetcode.qualifier.PersonQ;
  6. import org.springframework.context.annotation.Configuration;
  7. @Configuration
  8. public class PersonFactory {
  9. @PersonQ("student")
  10. public Person createStudent() {
  11. return new Student();
  12. }
  13. @PersonQ("manager")
  14. public Person createManager() {
  15. return new Manager();
  16. }
  17. }

PersonFactory中,我们使用@PersonQ识别创建了哪种类型的 bean。

com/zetcode/MyRunner.java

  1. package com.zetcode;
  2. import com.zetcode.model.Person;
  3. import com.zetcode.qualifier.PersonQ;
  4. import org.slf4j.Logger;
  5. import org.slf4j.LoggerFactory;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.boot.CommandLineRunner;
  8. import org.springframework.stereotype.Component;
  9. @Component
  10. public class MyRunner implements CommandLineRunner {
  11. private static final Logger logger = LoggerFactory.getLogger(MyRunner.class);
  12. @Autowired
  13. @PersonQ("student")
  14. private Person p1;
  15. @Autowired
  16. @PersonQ("manager")
  17. private Person p2;
  18. @Override
  19. public void run(String... args) throws Exception {
  20. logger.info("{}", p1.info());
  21. logger.info("{}", p2.info());
  22. }
  23. }

MyRunner中,我们注入带有@Autowired@PersonQ注解的 bean。

com/zetcode/Application.java

  1. package com.zetcode;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. @SpringBootApplication
  5. public class Application {
  6. public static void main(String[] args) {
  7. SpringApplication.run(Application.class, args);
  8. }
  9. }

Application中,我们设置了 Spring Boot 应用。

您可能也对 Java 教程感兴趣,或列出所有 Spring Boot 教程