You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

策略模式实现类中无法访问依赖注入对象问题求助

解决策略模式中依赖注入对象空指针问题

问题根源

你的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动态获取策略(更灵活)

如果后续要扩展更多策略,这种方式无需修改工厂代码:

  1. 给每个策略类添加@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支付逻辑
    }
}
  1. 改造工厂,通过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. 主程序同样通过容器注入工厂使用,逻辑同方案1。

核心要点

所有需要依赖注入的Bean必须由CDI容器创建和管理,禁止手动用new创建容器Bean实例,否则容器无法完成依赖注入操作。

内容的提问来源于stack exchange,提问作者Houssem Salem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 19:33:09