策略模式实现类中无法访问依赖注入对象问题求助
解决策略模式中依赖注入对象空指针问题
问题根源
你的CreditCardStrategy和PayPalStrategy标注了@ApplicationScoped,属于CDI容器管理的Bean,但PaymentStrategyFactory中通过new CreditCardStrategy()手动创建实例——这种方式创建的对象不受容器控制,容器不会自动注入@Inject标记的依赖(apiExample、service),因此调用方法时会触发空指针异常。
解决方案
方案1:将工厂改为CDI管理Bean,直接注入策略实例
改造工厂类,让它也被容器管理,同时注入所有策略实现类:
@ApplicationScoped public class PaymentStrategyFactory { @Inject CreditCardStrategy creditCardStrategy; @Inject PayPalStrategy payPalStrategy; public PaymentStrategy getPaymentStrategy(String paymentMethod) { if ("creditcard".equals(paymentMethod)) { return creditCardStrategy; } else if ("paypal".equals(paymentMethod)) { return payPalStrategy; } else { throw new IllegalArgumentException("Invalid payment method: " + paymentMethod); } } }
主程序中不能直接new工厂,要通过容器注入获取:
// 在业务类中注入工厂(以Quarkus/Spring等CDI环境为例) @Inject PaymentStrategyFactory factory; public void executePayment() { String paymentMethod = "creditcard"; PaymentStrategy paymentStrategy = factory.getPaymentStrategy(paymentMethod); PaymentProcessor paymentProcessor = new PaymentProcessor(paymentStrategy); paymentProcessor.processPayment(100.0); }
方案2:用CDI Instance动态获取策略(更灵活)
如果后续要扩展更多策略,这种方式无需修改工厂代码:
- 给每个策略类添加
@Named注解,指定唯一标识:
@ApplicationScoped @Named("creditcard") public class CreditCardStrategy implements PaymentStrategy { @Inject @RestClient ApiExample apiExample; @Override public void processPayment(double amount) { apiExample.doSomething(); // 信用卡支付逻辑 } } @ApplicationScoped @Named("paypal") public class PayPalStrategy implements PaymentStrategy { @Inject Service service; @Override public void processPayment(double amount) { service.doSomething(); // PayPal支付逻辑 } }
- 改造工厂,通过
Instance<PaymentStrategy>动态选择策略:
import jakarta.enterprise.inject.Instance; import jakarta.inject.Named; import jakarta.enterprise.util.AnnotationLiteral; @ApplicationScoped public class PaymentStrategyFactory { @Inject Instance<PaymentStrategy> paymentStrategyInstances; public PaymentStrategy getPaymentStrategy(String paymentMethod) { return paymentStrategyInstances.select(new NamedLiteral(paymentMethod)).get(); } // 定义Named注解的字面量类 private static class NamedLiteral extends AnnotationLiteral<Named> implements Named { private final String value; public NamedLiteral(String value) { this.value = value; } @Override public String value() { return value; } } }
- 主程序同样通过容器注入工厂使用,逻辑同方案1。
核心要点
所有需要依赖注入的Bean必须由CDI容器创建和管理,禁止手动用new创建容器Bean实例,否则容器无法完成依赖注入操作。
内容的提问来源于stack exchange,提问作者Houssem Salem
相关产品推荐
相关产品推荐

