确定在Spring Boot应用程序中使用哪种实现

时间:2019-01-23 20:09:52

标签: java spring

给定一个特定服务API的两个(或多个)实现,基于应用程序属性在我的应用程序中选择在运行时使用哪一个的最佳方法是什么?

示例API:

public interface Greeting {
    String sayHello(String username);
}

实施:

public class FriendlyGreeting implements Greeting {
    public String sayHello(String username) {
        return "Hello, " + username;
    }
} 

public class HostileGreeting implements Greeting {
    public String sayHello(String username) {
        return "Go away, " + username;
    }
}

我有一个带有@Autowired构造函数的独立服务类,该构造函数采用Greeting的实例。我想要的是基于配置属性,以确定要注入和使用的问候语实现。我想出了使用配置类做出决定的方法:

@Configuration
public class GreetingConfiguration {
    private String selection;

    @Autowired
    public GreetingConfiguration(@Value("${greeting.type}") String type) {
        this.selection = type;
    }

    @Bean
    public Greeting provideGreeting() {
        if ("friendly".equals(selection)) {
            return new FriendlyGreeting();
        } else {
            return new HostileGreeting();
        }
    }
}

这是正确做我想要的事情的方法吗?我走过在实现上使用@Qualifier的道路,最后陷入一片混乱,Spring看到了我的Greeting API的3个实例,无论如何我都需要一个配置来选择要使用并返回的实现它上面有一个唯一的限定词名称,这感觉比我确定的要差。

4 个答案:

答案 0 :(得分:1)

您可以使用https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Conditional.htmlhttps://reflectoring.io/spring-boot-conditionals/

中描述的Array注解 上面提到的

@Conditional注释基于@Profile(来自Spring Framework);另请参阅Spring Boot:org.springframework.boot.autoconfigure.condition

答案 1 :(得分:0)

您可以将Greeting都标记为@Service,并使用@Qualifier(“ yourServiceHere”)选择所选择的一个,如下所示:

@Autowired
@Qualifier("friendlyGreeting")
private Greeting greeting;

另一种方法是使用个人资料。您可以使用@Service和@Profile(“ friendly”)标记您的FriendlyGreeting服务,并使用@Service和@Profile(“ hostileGreeting”)标记HostileGreeting服务,然后将以下内容放入application.properties:

spring.profiles.active=friendly

答案 2 :(得分:0)

回答我自己的问题。

@Compass@user268396是正确的-使用“个人档案”可以按预期工作。

我创建了两个实现,并用@Service和@Profile(“ friendly”)或@Profile(“ hostile”)进行了注释,并且可以将属性spring.profiles.active更改为dev,friendly,并获得我想要的。

答案 3 :(得分:0)

这是一个完整的解决方案,使用上面 David 和 Vitor 提到的想法以及@Profile 和 @Qualifer 注释。

两个具有相同名称的 bean,但根据定义的配置文件仅激活一个 bean。

@Profile("profile1")
@Bean("greeting")
public class FriendlyGreeting implements Greeting {

---

@Profile("profile2")
@Bean("greeting")
public class HostileGreeting implements Greeting {

---

@Configuration
public class GreetingConfiguration {

    private Greeting greeting;

    @Autowired
    public GreetingConfiguration(@Qualifier("greeting") Greeting greeting) {
        this.greeting = greeting;
    }

}

注意事项:

  • 您可以移除中间类 GreetingConfiguration 并将“greeting”bean 粘贴到您需要的任何位置
  • 我更喜欢构造函数上的 @Autowired 而不是类成员,以便更轻松地进行单元测试。