java - SpringBoot : Configurable @Qualifier to select bean

标签 java spring spring-boot qualifiers

关于 SpringBoot 的小问题,以及如何使用 @Qualifier 配置 bean。

我有一段非常简单的代码:

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

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.1</version>
        <relativePath/>
    </parent>

    <groupId>com.question</groupId>
    <artifactId>language</artifactId>
    <version>1.1</version>

    <name>language</name>
    <description>Spring Boot</description>

    <properties>
        <java.version>17</java.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

package com.question;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class LanguageApplication {

    public static void main(String[] args) {
        SpringApplication.run(LanguageApplication.class, args);
    }

}
package com.question.service;

public interface LanguageService {

    String process(String name);

}

package com.question.service;

import org.springframework.stereotype.Service;

@Service("french")
public class FrenchLanguageServiceImpl implements LanguageService {

    @Override
    public String process(String name) {
        return "Bonjour " + name;
    }

}

package com.question.service;

import org.springframework.stereotype.Service;

@Service("english")
public class EnglishLanguageServiceImpl implements LanguageService {

    @Override
    public String process(String name) {
        return "Welcome " + name;
    }

}

package com.question.controller;

import com.question.service.LanguageService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

@RestController
public class LanguageController {

    private final LanguageService languageService;

    @Value("${configuration}")
    public String configuration;

    public LanguageController(@Qualifier(configuration) LanguageService languageService) {
        this.languageService = languageService;
    }

    @GetMapping("/test")
    public String test(@RequestParam String name) {
        return languageService.process(name);
    }

}

预期:

我希望实现的目标同样简单。我想将某种配置传递给 application.properties,例如 configuration=frenchconfiguration=english

在 Controller 层,使用(@Qualifier(configuration) LanguageService languageService)并且将使用正确的具体服务。

实际:

不幸的是,

@Qualifier(configuration) + @Value("${configuration}") public String 配置;

将产生属性值必须是常量

有没有办法我们可以通过可配置的@Qualifier来配置具体的Bean?

我知道有一种方法可以通过使用 ApplicationContext getBean 来解决此问题。

但是有了这个构造:@Qualifier(configuration) 使代码干净且易于理解。请问如何实现这一点?

谢谢

最佳答案

如果您一次只需要 1 个处于 Activity 状态的 LanguageService bean,那么您可以对每个 bean 使用 @ConditionalOnProperty,每个 bean 都使用唯一的 havingValue 。像这样(警告,从内存中编写的未经测试的代码):

interface ConfigKeys {
    public static final String LANGUAGE = "my.app.prefix.language";
}


@Service
@ConditionalOnProperty(name = ConfigKeys.LANGUAGE, havingValue = "english")
public class EnglishLanguageServiceImpl implements LanguageService {

    @Override
    public String process(String name) {
        return "Welcome " + name;
    }

}

@Service
@ConditionalOnProperty(name = ConfigKeys.LANGUAGE, havingValue = "french")
public class FrenchLanguageServiceImpl implements LanguageService {

    @Override
    public String process(String name) {
        return "Bonjour " + name;
    }

}

这样,您不需要任何限定符,只需将配置(application.properties 或 application.yaml)中的 my.app.prefix.language 属性设置为您想要的值,并且上下文中只有一个 LanguageService bean。您可以在任何需要的地方注入(inject)该 Bean,而无需限定符。

关于java - SpringBoot : Configurable @Qualifier to select bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75109389/

相关文章:

spring - 如何从 java 代码配置 spring boot 服务器(初始化时)?

java - 创建 REST API 以在 Spring Boot 中上传多部分文件数据

java - 将项目从一个 JComboBox 传输到另一个 JComboBox

java - 在 Java 中输入字符串的每个单词的末尾 append 一个字符串

java - java中的Strictfp方法有什么用?

java - 当我们在 Spring Boot 中使用 JPA Repository 时,List<Object> 默认大小是多少?

java - 动态插件架构。从 Spring boot 应用程序的目录加载 jar 文件

java - SWT/JFace : remove widgets

java - Spring data mongodb 模拟 ifNull 行为

java - 包含在正文中时缺少请求参数