Spring Dependency Injection缺少bean

时间:2019-12-23 11:23:08

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

我试图用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正常工作,我缺少什么?

3 个答案:

答案 0 :(得分:2)

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

@Service
public class DeckManager implements IDeckManager {

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

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

答案 1 :(得分:1)

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

并且,请问Java和Spring具有自己的命名约定...名称InintializeDeckShuffleDeck对于方法名称而言是不正确的!使用initializeDeckshuffleDeck

答案 2 :(得分:1)

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

但是,我想在这里澄清一件事,这可能会使您免于可能的错误。

Spring bean默认情况下是单例,因此spring将有一个DeckManager实例注入到控制器。我认为它应该管理一副纸牌。

因此,当您致电/prepareDeck时,它的确会创建一个牌组并将其充满卡片,到目前为止,一切都很好。但是,如果您(或其他人)会再次调用此HTTP方法呢?

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

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

可以为卡片组管理器创建一个“ init”方法,并使用@PostConstruct注释对其进行注释。在此方法中,您可以创建一个卡片组,并且不需要HTTP方法。在初始化过程中,Spring只会调用一次此方法。