ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
# Spring Boot `@Qualifier`教程 > 原文: [http://zetcode.com/springboot/qualifier/](http://zetcode.com/springboot/qualifier/) Spring Boot `@Qualifier`教程展示了如何使用`@Qualifier`来区分相同类型的 bean。 它也可以用于注解其他自定义注解,这些注解随后可以用作限定符。 Spring 是流行的 Java 应用框架,而 Spring Boot 是 Spring 的演进,可帮助您以最少的精力创建独立的,生产级的基于 Spring 的应用。 以下三个应用是命令行 Spring Boot 应用。 ## `@Qualifier` `Person` bean 在我们的应用中,我们有两个`Person`类型的 bean:`Student`和`Manager`。 我们使用`@Qualifier`注解来区分它们。 ```java pom.xml src ├───main │ ├───java │ │ └───com │ │ └───zetcode │ │ │ Application.java │ │ │ MyRunner.java │ │ └───model │ │ Manager.java │ │ Person.java │ │ Student.java │ └───resources └───test └───java ``` 这是 Spring Boot 应用的项目结构。 `pom.xml` ```java <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zetcode</groupId> <artifactId>springbootqualifier</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.5.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> ``` 这是 Maven 构建文件。 `spring-boot-starter`是包括自动配置支持,日志记录和 YAML 在内的核心启动器。 该应用打包到一个 JAR 文件中。 `com/zetcode/model/Person.java` ```java package com.zetcode.model; public interface Person { String info(); } ``` 我们有一个定义`Person`类型的接口。 `com/zetcode/model/Student.java` ```java package com.zetcode.model; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @Component @Qualifier("student") public class Student implements Person { @Override public String info() { return "Student"; } } ``` `Student`继承自`Person`。 `@Component`是基本的 Spring 注解,它允许 Spring 容器检测`Student`。 `@Qualifier("student")`用`"student"`字符串唯一标识此 bean。 `com/zetcode/model/Manager.java` ```java package com.zetcode.model; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @Component @Qualifier("manager") public class Manager implements Person { @Override public String info() { return "Manager"; } } ``` 我们还有另一个名为`Manager`的 bean。 该 bean 也用`@Qualifier("manager")`注解标识。 `com/zetcode/MyRunner.java` ```java package com.zetcode; import com.zetcode.model.Person; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; @Component public class MyRunner implements CommandLineRunner { private static final Logger logger = LoggerFactory.getLogger(MyRunner.class); @Autowired @Qualifier("student") private Person p1; @Autowired @Qualifier("manager") private Person p2; @Override public void run(String... args) throws Exception { logger.info("{}", p1.info()); logger.info("{}", p2.info()); } } ``` `CommandLineRunner`接口指示当`SpringApplication`中包含 bean 时应运行它。 它可以用来在 Spring Boot 中创建命令行应用。 ```java @Component public class MyRunner implements CommandLineRunner { ``` `CommandLineRunner`也是一个 Spring bean,并用`@Component`注解装饰。 它由 Spring 自动检测。 ```java @Autowired @Qualifier("student") private Person p1; ``` 我们将`Person` bean 注入`p1`字段。 `@Qualifier("student")`指定它是一个`Student` bean。 ```java @Autowired @Qualifier("manager") private Person p2; ``` 同样,我们将`Manager` bean 注入`p2`字段。 `com/zetcode/Application.java` ```java package com.zetcode; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` `Application`设置 Spring Boot 应用。 `@SpringBootApplication`注解启用自动配置和组件扫描。 ## 使用工厂创建 bean 在第二个应用中,我们使用工厂类来生成 bean。 `pom.xml`,`Person.java`,`Application.java`和`MyRunner.java`保持不变。 ```java pom.xml src ├───main │ ├───java │ │ └───com │ │ └───zetcode │ │ │ Application.java │ │ │ MyRunner.java │ │ ├───conf │ │ │ PersonFactory.java │ │ └───model │ │ Manager.java │ │ Person.java │ │ Student.java │ └───resources └───test └───java ``` 这是项目结构。 `com/zetcode/model/Manager.java` ```java package com.zetcode.model; public class Manager implements Person { @Override public String info() { return "Manager"; } } ``` 注解已从`Manager`类中删除。 `com/zetcode/model/Student.java` ```java package com.zetcode.model; public class Student implements Person { @Override public String info() { return "Student"; } } ``` 同样,`Student`类没有注解。 `com/zetcode/conf/PersonFactory.java` ```java package com.zetcode.conf; import com.zetcode.model.Manager; import com.zetcode.model.Person; import com.zetcode.model.Student; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class PersonFactory { @Bean @Qualifier("student") public Person createStudent() { return new Student(); } @Bean @Qualifier("manager") public Person createManager() { return new Manager(); } } ``` 在前面的示例中,Spring 会自动检测到这些 bean。 在这里,`PersonFactory`借助`@Bean`注解创建了两个 bean。 ```java @Bean @Qualifier("student") public Person createStudent() { return new Student(); } ``` `@Bean`注解标记了定义 bean 的方法。 `@Qualifier("student")`指示要创建`Person`的哪个实现。 ## 创建自定义`@Qualifier`注解 为了减少代码,我们可以创建自定义`@Qualifier`注解。 ```java pom.xml src ├───main │ ├───java │ │ └───com │ │ └───zetcode │ │ │ Application.java │ │ │ MyRunner.java │ │ ├───conf │ │ │ PersonFactory.java │ │ ├───model │ │ │ Manager.java │ │ │ Person.java │ │ │ Student.java │ │ └───qualifier │ │ PersonQ.java │ └───resources └───test └───java ``` 这是项目结构; 我们列出了第一个应用中列出的`pom.xml`以外的所有文件。 `com/zetcode/model/Person.java` ```java package com.zetcode.model; public interface Person { String info(); } ``` 这是`Person`类型。 `com/zetcode/model/Manager.java` ```java package com.zetcode.model; import org.springframework.stereotype.Component; @Component public class Manager implements Person { @Override public String info() { return "Manager"; } } ``` `Manager`类装饰有`@Component`注解; 它将由 Spring 自动检测。 `com/zetcode/model/Student.java` ```java package com.zetcode.model; import org.springframework.stereotype.Component; @Component public class Student implements Person { @Override public String info() { return "Student"; } } ``` `Student`的情况相同。 `com/zetcode/qualifier/PersonQ.java` ```java package com.zetcode.qualifier; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.beans.factory.annotation.Qualifier; @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Qualifier public @interface PersonQ { String value(); } ``` 在这里,我们定义了一个新的`@PersonQ`限定符。 ```java @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) ``` `@Targer`注解指出可以在何处应用注解。 在我们的情况下,它可以应用于字段,方法和参数。 ```java @Retention(RetentionPolicy.RUNTIME) ``` `@Retention`注解指定标记的注解的存储方式。 使用`RetentionPolicy.RUNTIME`,标记的注解将由 JVM 保留,因此可以由运行时环境使用。 ```java public @interface PersonQ { ``` `@interface`关键字用于声明新的注解类型。 `com/zetcode/conf/PersonFactory.java` ```java package com.zetcode.conf; import com.zetcode.model.Manager; import com.zetcode.model.Person; import com.zetcode.model.Student; import com.zetcode.qualifier.PersonQ; import org.springframework.context.annotation.Configuration; @Configuration public class PersonFactory { @PersonQ("student") public Person createStudent() { return new Student(); } @PersonQ("manager") public Person createManager() { return new Manager(); } } ``` 在`PersonFactory`中,我们使用`@PersonQ`识别创建了哪种类型的 bean。 `com/zetcode/MyRunner.java` ```java package com.zetcode; import com.zetcode.model.Person; import com.zetcode.qualifier.PersonQ; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; @Component public class MyRunner implements CommandLineRunner { private static final Logger logger = LoggerFactory.getLogger(MyRunner.class); @Autowired @PersonQ("student") private Person p1; @Autowired @PersonQ("manager") private Person p2; @Override public void run(String... args) throws Exception { logger.info("{}", p1.info()); logger.info("{}", p2.info()); } } ``` 在`MyRunner`中,我们注入带有`@Autowired`和`@PersonQ`注解的 bean。 `com/zetcode/Application.java` ```java package com.zetcode; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 在`Application`中,我们设置了 Spring Boot 应用。 您可能也对 [Java 教程](/lang/java/)感兴趣,或列出[所有 Spring Boot 教程](/all/#springboot)。