抱歉,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时,都必须在枚举中仅添加一个条目,并添加新网关的实现。

10-08 00:34