【问题标题】:Spring Dependency Injection missing beanSpring依赖注入缺少bean
【发布时间】:2020-04-14 16:38:22
【问题描述】:

我正在尝试使用 Spring 实现基于构造函数的依赖注入。 从 Spring 4.3 开始,构造函数注入不需要注解,所以我的类看起来像这样:

@RestController
public class CardController {

    private IDeckManager _deckManager;

    public CardController(IDeckManager deckManager){
        _deckManager = deckManager;
    }

    @RequestMapping("/preparedeck")
    public void PrepareDeck(){
        _deckManager.InitializeDeck();
        _deckManager.ShuffleDeck();
    }
}

IDeckManager 在哪里:

public interface IDeckManager {

    void InitializeDeck();

    void ShuffleDeck();
}

而IDeckManager的实际实现是:

public class DeckManager implements IDeckManager {

    public Stack<Card> deck;

    public DeckManager() {
        deck = new Stack<Card>();
    }

    @Override
    public void InitializeDeck() {

        for (int i = 0; i < ICard.Suit.length; i++) {
            for (int j = 0; i < ICard.Values.length; i++) {
                deck.add(new Card(ICard.Suit[i], ICard.Values[j]));
            }
        }
    }

    @Override
    public void ShuffleDeck() {
        Collections.shuffle(deck);
    }
}

不幸的是,在运行时它说:CardController 中构造函数的参数 0 需要一个 IDeckManager 类型的 bean,但无法找到。

为了让 DI 正常工作,我缺少什么?

【问题讨论】:

标签: java spring spring-boot dependency-injection spring-annotations


【解决方案1】:

Spring需要将DeckManager识别为Spring托管bean,如果你使用组件扫描在实现上添加@Service或@Component注解

@Service
public class DeckManager implements IDeckManager {

或者将其作为 Bean 添加到 Configuration 类中

@Bean
IDeckManager deckManager() {
   return new DeckManager();
}

【讨论】:

    【解决方案2】:

    DeckManager 应该是 Spring 的一个组件 - @Component、@Service 等。或者只是 @Bean。

    请注意,Java 和 Spring 有自己的命名约定……名称 InintializeDeck 和 ShuffleDeck 对于方法名称不正确!使用initializeDeck 和shuffleDeck。

    【讨论】:

      【解决方案3】:

      正如我们的同事已经说过的,DeckManager 类必须由 Spring 管理,并且添加 @Component 或 @Service 注释将解决该问题。

      不过,我想在此澄清一件事,这可能会使您免于可能出现的错误。

      Spring bean 默认是单例的,所以会有一个 DeckManager 的实例由 spring 注入到控制器中。我认为它应该管理纸牌。

      所以当你调用/prepareDeck 时,它确实会创建一个套牌并用卡片填充它,到目前为止一切都很好。但是,如果您(或其他人)再次调用此 HTTP 方法怎么办?

      答案是它会创建另一个系列的卡片并将其放入堆栈。本质上,它会为每次调用添加另外 N 张卡片,这可能不是您想要的。

      另一个用例:如果同时调用两个(或多个)“初始化卡组”请求怎么办?内部堆栈将包含奇怪的卡片组合...同样,可能不是您的目标。

      可以为甲板管理器创建一个“init”方法并使用@PostConstruct 注释对其进行注释。在这种方法中,您可以创建一个卡片组,而您不需要 HTTP 方法。 Spring 将在初始化期间仅调用一次此方法。

      【讨论】:

      • 首先非常感谢您!我没有选择您的答案,原因很简单,即“user7294900”这个问题排在第一位,而且它适用于我的问题,因此对于未来的读者来说,它是最好的答案。但我仍然要感谢您的反馈。我来自 .NET 世界,所有这些 Spring 的东西对我来说都是新的。我会用一个简单的“if(deck.Empty())”解决你指出的错误,以这样一种方式初始化发生一次,但多亏了你,我学到了一个超级方便的新东西!所以,非常感谢! :)
      猜你喜欢
      • 2012-08-02
      • 1970-01-01
      • 2014-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多