我试图用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正常工作,我缺少什么?
答案 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具有自己的命名约定...名称InintializeDeck
和ShuffleDeck
对于方法名称而言是不正确的!使用initializeDeck
和shuffleDeck
。
答案 2 :(得分:1)
正如我们的同事已经指出的那样,DeckManager
类必须由Spring管理,并放置一个@Component
或@Service
注释才能解决问题。
但是,我想在这里澄清一件事,这可能会使您免于可能的错误。
Spring bean默认情况下是单例,因此spring将有一个DeckManager
实例注入到控制器。我认为它应该管理一副纸牌。
因此,当您致电/prepareDeck
时,它的确会创建一个牌组并将其充满卡片,到目前为止,一切都很好。但是,如果您(或其他人)会再次调用此HTTP方法呢?
答案是,它将创建另一系列的卡并将其放入堆栈。本质上,每次调用将添加另外N张卡,这可能不是您想要的。
另一个用例:如果两个(或多个)“初始化卡片组”请求同时被调用怎么办?内部堆栈将包含奇怪的纸牌组合...同样,可能不是您的目标。
可以为卡片组管理器创建一个“ init”方法,并使用@PostConstruct
注释对其进行注释。在此方法中,您可以创建一个卡片组,并且不需要HTTP方法。在初始化过程中,Spring只会调用一次此方法。