Spring 依赖注入缺少 bean

Spring Dependency Injection missing bean

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

@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 正常工作?

Spring 需要将 DeckManager 标识为 Spring 托管 bean,如果您使用组件扫描,请在实现上添加 @Service@Component 注释

@Service
public class DeckManager implements IDeckManager {

或者将其作为 Bean

添加到配置 class 中
@Bean
IDeckManager deckManager() {
   return new DeckManager();
}

DeckManager 应该是 Spring 的组成部分 - @Component@Service 等。或者只是 @Bean.

请注意,Java 和 Spring 有自己的命名约定……名称 InintializeDeckShuffleDeck 的方法名称不正确!使用 initializeDeckshuffleDeck.

正如我们的同事已经指出的那样,DeckManager class 必须由 Spring 管理并且放置 @Component@Service 注释将解决问题。

不过,我想在这里澄清一件事,这可能会让您避免可能出现的错误。

默认情况下,

Spring bean 是单例,因此 spring 将向控制器注入 DeckManager 的单个实例。我认为它应该管理一副纸牌。

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

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

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

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