抱歉,Spring是我的新手。我想根据用户的输入值动态注入或获取bean。
例如:
public interface PaymentGateway {}
public class PayPal implement PaymentGateway {}
public class Stripe implement PaymentGateway {}
public class Square implement PaymentGateway {}
public class PaymentService {
@Autowired
private final PaymentGateway gateway;
// TODO
}
我让用户选择一个支付网关(PayPal或Stripe或Square),然后注入PaymentGateway进行处理。如何动态注入或获取bean?
非常感谢!
最佳答案
我认为您有多种方法可以做到这一点。
其中之一将是下一个。
我看到PaymentGateway
是一个private final
,即使您将@Autowired
放在成员字段的顶部,它也会强制您使用构造函数注入。这意味着您可以通过以下方式将PaymentService
创建为bean:
@Bean
public PaymentService paymentService(PaymentGateway gw) {
return new PaymentService(gw);
}
在这里,您可以让您的客户使用任何
PaymentGateway
实现。编辑
以后的编辑是为了引入
Dispatcher
来找到正确的PaymentGateway
bean。首先,介绍一个枚举类型
enum PmtGatewayType {
PayPal,
Stripe,
Square
}
现在,在
PaymentGateway
界面中添加类似于以下方法的方法:public boolean accept(PmtGatewayType pmtGatewayType);
并以以下方式实施:
class Stripe implements PaymentGateway {
private PmtGatewayType gwType;
@Override
public boolean accept(PmtGatewayType pmtGwType) {
return gwType.equals(pmtGwType);
}
现在,您可以创建另一个名为
PmtGwDispatcher
的类,在其中将注入所有List
bean的PaymentGateway
,如下所示:@Component
class PmtGwDispacher {
@Autowired
private List<PaymentGateway> pmtGateways;
public PaymentGateway select(PmtGatewayType gwType) {
PaymentGateway gw = pmtGateways.stream().filter(gw -> gw.accept(gwType)).findFirst().get();
if(gw == null) {
throw new IllegalArgumentException("The provided gateway type is invalid");
}
}
现在,在
PaymentService
中,您可以注入PmtGwDispatcher
并使用它。解决方案有点复杂,但是它遵循SOLID原则。每个组件都遵循SRP,并且每次需要添加新的
PaymentGateway
时,都必须在枚举中仅添加一个条目,并添加新网关的实现。