public interface GreetingService {
void doGreetings();
}
您有两个实施HelloService
@Service
@Slf4j
public class HelloService implements GreetingService{
@Override
public void doGreetings() {
log.info("Hello world!");
}
}
和HiService的值
@Slf4j
@Service
public class HiService implements GreetingService{
@Override
public void doGreetings() {
log.info("Hi world!");
}
}
然后,您有另一个接口,即BusinessService,用于调用一些业务
public interface BusinessService {
void doGreetings();
}
有一些方法可以做到这一点
**#1.**使用@Autowired
@Component
public class BusinessServiceImpl implements BusinessService{
@Autowired
private GreetingService hiService; // Spring automatically maps the name for you, if you don't want to change it.
@Autowired
private GreetingService helloService;
@Override
public void doGreetings() {
hiService.doGreetings();
helloService.doGreetings();
}
}
@Component
public class BusinessServiceImpl implements BusinessService {
private final GreetingService hiService;
private final GreetingService helloService;
public BusinessServiceImpl(GreetingService hiService, GreetingService helloService) {
this.hiService = hiService;
this.helloService = helloService;
}
@Override
public void doGreetings() {
hiService.doGreetings();
helloService.doGreetings();
}
}
这可
public BusinessServiceImpl(@Qualifier("hiService") GreetingService hiService, @Qualifier("helloService") GreetingService helloService)
但我使用的是Sping Boot 2.6.5和
public BusinessServiceImpl(GreetingService hiService, GreetingService helloService)
工作正常,因为Spring会自动为我们获取名称。
#3。您也可以使用Map来执行此操作
@Component
@RequiredArgsConstructor
public class BusinessServiceImpl implements BusinessService {
private final Map<String, GreetingService> servicesMap; // Spring automatically get the bean name as key
@Override
public void doGreetings() {
servicesMap.get("hiService").doGreetings();
servicesMap.get("helloService").doGreetings();
}
}
如果你运行所有的服务,List也能正常工作。但是如果你想得到一些特定的实现,你需要为它定义一个名字或类似的东西。我的参考is here 对于这一个,我使用来自Lombok岛的@RequiredArgsConstructor。
public interface SomeInterfaces {
void send(String message);
String getType();
}
Kafka服务
@Component
public class SomeInterfacesKafkaImpl implements SomeInterfaces {
private final String type = "kafka";
@Override
public void send(String message) {
System.out.println(message + "through Kafka");
}
@Override
public String getType() {
return this.type;
}
}
再服务
@Component
public class SomeInterfacesRedisImpl implements SomeInterfaces {
private final String type = "redis";
@Override
public void send(String message) {
System.out.println(message + "through Redis");
}
@Override
public String getType() {
return this.type;
}
}
主设备
@Component
public class SomeInterfacesMaster {
private final Set<SomeInterfaces> someInterfaces;
public SomeInterfacesMaster(Set<SomeInterfaces> someInterfaces) {
this.someInterfaces = someInterfaces;
}
public void sendMaster(String type){
Optional<SomeInterfaces> service =
someInterfaces
.stream()
.filter(service ->
service.getType().equals(type)
)
.findFirst();
SomeInterfaces someService =
service
.orElseThrow(() -> new RuntimeException("There is not such way for sending messages."));
someService .send(" Hello. It is a letter to ....");
}
}
试验,测验
@SpringBootTest
public class MultiImplementation {
}
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class SomeInterfacesMasterTest extends MultiImplementation {
@Autowired
private SomeInterfacesMaster someInterfacesMaster;
@Test
void sendMaster() {
someInterfacesMaster.sendMaster("kafka");
}
}
因此,根据Open/Closed原则,我们只需要添加一个实现,而不会破坏现有代码。
@Component
public class SomeInterfacesRabbitImpl implements SomeInterfaces {
private final String type = "rabbit";
@Override
public void send(String message) {
System.out.println(message + "through Rabbit");
}
@Override
public String getType() {
return this.type;
}
}
public class Employee {
private String mobileNumber;
private String emailAddress;
...
/**Getters & Setters omitted**/
}
接口员工验证器:
public interface EmployeeValidator {
public Employee validate(Employee employee);
}
移动的号码验证程序的第一个实现类:
@Component(value="EmployeeMobileValidator")
public class EmployeeMobileValidator implements EmployeeValidator {
@Override
public Employee validate(Employee employee) {
//Mobile number Validation logic goes here.
}
}
电子邮件地址验证器的第二个实现类:
@Component(value="EmployeeEmailValidator")
public class EmployeeEmailValidator implements EmployeeValidator {
@Override
public Employee validate(Employee employee) {
//Email address validation logic goes here.
}
}
我们现在可以自动将上面的这些验证器分别连接到一个类中。
员工服务界面:
public interface EmployeeService {
public void handleEmployee(Employee employee);
}
员工服务实现类
@Service
public class EmployeeServiceImpl implements EmployeeService {
/**Autowire validators individually**/
@Autowired
@Qualifier("EmployeeMobileValidator") // Autowired using qualifier for mobile validator
private EmployeeValidator mobileValidator;
@Autowired
@Qualifier("EmployeeEmailValidator") // Autowired using qualifier for email valodator
private EmployeeValidator emailValidator;
@Override
public void handleEmployee(Employee employee) {
/**You can use just one instance if you need**/
employee = mobileValidator.validate(employee);
}
}
7条答案
按热度按时间1cklez4t1#
使用
@Qualifier
注解用于区分相同接口的bean查看Sping Boot 文档
此外,要注入同一接口的所有bean,只需 autowire
List
of interface(The与Spring / Sping Boot / SpringBootTest中的方法相同)
示例如下:
对于您问题的第二部分,请查看以下有用的答案first/second
6bc51xsx2#
您还可以通过为它指定实现的名称来使它工作。
例如:
cbeh67ev3#
假设您有
GreetingService
您有两个实施
HelloService
和
HiService
的值然后,您有另一个接口,即
BusinessService
,用于调用一些业务有一些方法可以做到这一点
**#1.**使用
@Autowired
如果您需要更改实现Bean名称,请参考其他答案,方法是为Bean设置名称,例如
@Service("myCustomName")
并应用@Qualifier("myCustomName")
**#2.**您还可以使用构造函数注入
这可
但我使用的是Sping Boot
2.6.5
和工作正常,因为Spring会自动为我们获取名称。
#3。您也可以使用
Map
来执行此操作如果你运行所有的服务,
List
也能正常工作。但是如果你想得到一些特定的实现,你需要为它定义一个名字或类似的东西。我的参考is here对于这一个,我使用来自Lombok岛的
@RequiredArgsConstructor
。tuwxkamq4#
正如注解中提到的,通过使用
@Qualifier
注解,您可以区分文档中描述的不同实现。对于测试,您也可以使用执行相同的操作。例如:
2admgd595#
当我们对具有多个实现的接口进行自动配置时,有两种方法:
总之,它告诉我们的Spring应用程序,每当我们试图自动连接我们的接口时,要使用用@Primary注解标记的特定实现。它就像一个默认的自动连接设置。一个接口的每个实现簇只能使用一次。→ @Primary Docs
这个Spring注解给了我们更多的控制权来选择具体的实现,无论我们在什么地方定义一个接口的引用来选择它的选项。→ @Qualifier Docs
有关详细信息,请访问其文档的链接。
cwdobuhd6#
因此,根据Open/Closed原则,我们只需要添加一个实现,而不会破坏现有代码。
xn1cxnb47#
如果我们有同一个接口的多个实现,Spring需要知道它应该自动连接到一个类中。下面是一个 * Employee的移动的号码和电子邮件地址的验证器 * 的简单示例:-
员工类别:
接口员工验证器:
移动的号码验证程序的第一个实现类:
电子邮件地址验证器的第二个实现类:
我们现在可以自动将上面的这些验证器分别连接到一个类中。
员工服务界面:
员工服务实现类