简体   繁体   English

Spring依赖注入缺少bean

[英]Spring Dependency Injection missing bean

I am trying to implement Constructor based Dependency Injection with Spring.我正在尝试使用 Spring 实现基于构造函数的依赖注入。 From Spring 4.3 annotations are not required for constructor injection, so my class looks like this:从 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();
    }
}

where IDeckManager is: IDeckManager 在哪里:

public interface IDeckManager {

    void InitializeDeck();

    void ShuffleDeck();
}

and the actual implementation of IDeckManager is: 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);
    }
}

Unfortunately at runtime it says that: Parameter 0 of constructor in CardController required a bean of type IDeckManager that could not be found.不幸的是,在运行时它说: CardController 中构造函数的参数 0 需要一个无法找到的 IDeckManager 类型的 bean。

What am I missing to make the DI work properly?我缺少什么才能使 DI 正常工作?

Spring need to identify DeckManager as Spring managed bean, if you use component scan add @Service or @Component annotation on implementation Spring 需要将DeckManager标识为 Spring 托管 bean,如果使用组件扫描在实现上添加@Service@Component注解

@Service
public class DeckManager implements IDeckManager {

Or add it in Configuration class as a Bean或者将其作为 Bean 添加到 Configuration 类中

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

DeckManager should be a component of Spring - @Component , @Service , etc. Or just @Bean . DeckManager应该是 Spring 的一个组件 - @Component@Service等。或者只是@Bean

And, please, Java and Spring have own naming convention ... names InintializeDeck and ShuffleDeck are not correct for method names!而且,Java 和 Spring 有自己的命名约定......名称InintializeDeckShuffleDeck对于方法名称不正确! Use initializeDeck and shuffleDeck .使用initializeDeckshuffleDeck

As our colleagues already have stated, the DeckManager class has to be managed by Spring and putting a @Component or @Service annotation will resolve the issue.正如我们的同事已经说过的, DeckManager类必须由 Spring 管理,并且添加@Component@Service注释将解决该问题。

However I would like to clarify one additional thing here that might save you from a possible bug.但是,我想在这里澄清一件额外的事情,这可能会使您免于出现可能的错误。

Spring beans by default are singletons, so there will be a single instance of DeckManager injected by spring to controller. Spring bean 默认是单例的,所以会有一个由 spring 注入到控制器的DeckManager实例。 I assume it should manage deck of cards.我认为它应该管理一副纸牌。

So when you'll call /prepareDeck it will indeed create a deck and will fill it with the cards, so far so good.因此,当您调用/prepareDeck它确实会创建一副牌并用卡片填充它,到目前为止一切顺利。 However, what if you (or someone else) will call this HTTP method once again?但是,如果您(或其他人)再次调用此 HTTP 方法会怎样?

The answer is that it will create an another series of cards and will put it to the stack.答案是它会创建另一个系列的卡片并将其放入堆栈。 Essentially it will add another N cards per each invocation which is probably not what you want.从本质上讲,它会在每次调用时再添加 N 张卡,这可能不是您想要的。

Another use-case: What if two (or more) requests to "initialize deck" will be called simultaneously?另一个用例:如果同时调用两个(或多个)“初始化卡片组”的请求会怎样? The internal stack will contain a strange mix of cards... Again, probably not your goal.内部堆栈将包含奇怪的卡片组合......同样,可能不是您的目标。

Its possible to create an "init" method for deck manager and annotate it with @PostConstruct annotation.可以为甲板管理器创建一个“init”方法并使用@PostConstruct注释对其进行注释。 In this method you can create a deck and you won't need the HTTP method.在此方法中,您可以创建一个卡片组,并且不需要 HTTP 方法。 Spring will call this method exactly once during the initialization. Spring 将在初始化期间只调用一次此方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM