【问题标题】:Injecting service class by interface?通过接口注入服务类?
【发布时间】:2019-04-17 06:43:42
【问题描述】:

所以我有 2 个实现相同接口的服务类:

@Service
public class ServiceOne implements InterfaceOne {

}

@Service
public class ServiceTwo implements InterfaceOne {

}

我想知道如何在控制器中注入特定实例?

@RestController
@RequestMapping("/test")
public class MyController {
    @Inject
    public MyController(InterfaceOne service) {

    }
}

我不确定 DI 应该如何与服务类一起工作。基本上这两个服务类具有相同的接口,如果我可以将正确的接口注入控制器,我希望避免必要的情况。一个例子将不胜感激。

编辑:对不起,我不清楚。我还需要弄清楚的是,需要在控制器中注入哪个服务类而不指定具体的实现。所以,我希望有一种方法可以执行某种 if 语句并检查应该插入哪个服务实现。

【问题讨论】:

  • 您好,在这种情况下,我认为您应该在您的服务上使用@Qualifier
  • 你可以给他们起名字:stackoverflow.com/questions/48941960/…
  • 我认为您要么按照 Mickael 的建议使用 @Qualifier,要么将 @Autowire 特定服务而不是自动装配接口。
  • 对不起,我一开始并不清楚。我已经更新了描述

标签: java spring-boot


【解决方案1】:

处理多个实现时的两种方法:

使用由@Qualifier标识的特定风味

用特定的@Qualifier(例如@Qualifier("One")@Qualifier("Two"))注释每个实现,并注入特定的风味:

@Autowired
@Qualifier("One")
InterfaceOne implementation;

使用所有实现(或使用代码评估最合适的)

当您有一个策略接口并希望注入所有实现时,第二种方法很有用。然后,您可以使用它们中的所有或任何一个,还可以查询它们以获取更多详细信息。

在这种情况下(当期望 1..n 实现时),使用:

@Autowired
List<InterfaceOne> implementations;

如果实现是可选的 (0..n),请使用:

@Autowired
Optional<List<InterfaceOne>> implementations;

编辑:关于如何使用具有多个实现的策略接口的示例:

界面:

public interface HelloWorldService {
    String sayHello();
    String getLanguage();
}

实现:

@Service
public class HelloWorldServiceEN implements HelloWorldService {
    public String sayHello() { return "Hi there!"; }
    public String getLanguage() { return "en"; }
}

@Service
public class HelloWorldServiceDE implements HelloWorldService {
    public String sayHello() { return "Hallo!"; }
    public String getLanguage() { return "de"; }
}

@Service
public class HelloWorldServiceFR implements HelloWorldService {
    public String sayHello() { return "Salut!"; }
    public String getLanguage() { return "fr"; }
}

用法:

@Autowired
private List<HelloWorldService> helloWorldServices;

public void sayHelloInAllLanguages() {
    for (HelloWorldService helloWorldService : helloWorldServices) {
        System.out.println(helloWorldService.sayHello());
    }
}

public void sayHelloInUserLanguage() {
    String userLanguage = Locale.getDefault().getLanguage();
    HelloWorldService helloWorldService = find(userLanguage);
    System.out.println(helloWorldService.sayHello());

}

private HelloWorldService find(String language) {

    // find service in specific language
    Optional<HelloWorldService> service = helloWorldServices.stream().filter(s -> language.equals(s.getLanguage())).findFirst();
    if (service.isPresent()) {
        return service.get();
    }

    // fallback to english, if available
    service = helloWorldServices.stream().filter(s -> language.equals("en")).findFirst();
    if (service.isPresent()) {
        return service.get();
    }

    // fallback to any language
    return helloWorldServices.stream().findFirst().orElseThrow(IllegalStateException::new);
}

【讨论】:

  • 您好,如果您能举一个使用所有实现的用例示例,那就太好了。如何调用来自ServiceOne 实现的方法?
猜你喜欢
  • 1970-01-01
  • 2018-11-10
  • 2020-07-10
  • 2021-03-09
  • 2017-11-21
  • 2015-04-06
  • 2022-11-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多