Spring Boot @Qualifier 教程

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

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

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

@Qualifier Person bean

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

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

<?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

package com.zetcode.model;

public interface Person {

    String info();
}

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

com/zetcode/model/Student.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

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

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 中创建命令行应用。

@Component
public class MyRunner implements CommandLineRunner {

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

@Autowired
@Qualifier("student")
private Person p1;

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

@Autowired
@Qualifier("manager")
private Person p2;

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

com/zetcode/Application.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.xmlPerson.javaApplication.javaMyRunner.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

package com.zetcode.model;

public class Manager implements Person {

    @Override
    public String info() {

        return "Manager";
    }
}

注解已从Manager类中删除。

com/zetcode/model/Student.java

package com.zetcode.model;

public class Student implements Person {

    @Override
    public String info() {

        return "Student";
    }
}

同样,Student类没有注解。

com/zetcode/conf/PersonFactory.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。

@Bean
@Qualifier("student")
public Person createStudent() {

    return new Student();
}

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

创建自定义@Qualifier注解

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

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

package com.zetcode.model;

public interface Person {

    String info();
}

这是Person类型。

com/zetcode/model/Manager.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

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

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限定符。

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

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

@Retention(RetentionPolicy.RUNTIME)

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

public @interface PersonQ {

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

com/zetcode/conf/PersonFactory.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

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

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 应用。

赞(0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

Spring Boot 教程