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 有自己的命名约定……名称 InintializeDeck
和 ShuffleDeck
的方法名称不正确!使用 initializeDeck
和 shuffleDeck
.
正如我们的同事已经指出的那样,DeckManager
class 必须由 Spring 管理并且放置 @Component
或 @Service
注释将解决问题。
不过,我想在这里澄清一件事,这可能会让您避免可能出现的错误。
默认情况下,Spring bean 是单例,因此 spring 将向控制器注入 DeckManager
的单个实例。我认为它应该管理一副纸牌。
所以当您调用 /prepareDeck
时,它确实会创建一个牌组并用卡片填充它,到目前为止一切顺利。但是,如果您(或其他人)将再次调用此 HTTP 方法怎么办?
答案是它将创建另一系列的卡片并将其放入堆栈。本质上,它会在每次调用时添加另外 N 张卡片,这可能不是您想要的。
另一个用例:如果同时调用对 "initialize deck" 的两个(或更多)请求怎么办?内部堆栈将包含奇怪的卡片组合...同样,可能不是您的目标。
可以为甲板管理器创建一个 "init" 方法并用 @PostConstruct
注释对其进行注释。在这种方法中,您可以创建一个卡片组,并且不需要 HTTP 方法。 Spring 将在初始化期间恰好调用此方法一次。
我正在尝试使用 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 有自己的命名约定……名称 InintializeDeck
和 ShuffleDeck
的方法名称不正确!使用 initializeDeck
和 shuffleDeck
.
正如我们的同事已经指出的那样,DeckManager
class 必须由 Spring 管理并且放置 @Component
或 @Service
注释将解决问题。
不过,我想在这里澄清一件事,这可能会让您避免可能出现的错误。
默认情况下,Spring bean 是单例,因此 spring 将向控制器注入 DeckManager
的单个实例。我认为它应该管理一副纸牌。
所以当您调用 /prepareDeck
时,它确实会创建一个牌组并用卡片填充它,到目前为止一切顺利。但是,如果您(或其他人)将再次调用此 HTTP 方法怎么办?
答案是它将创建另一系列的卡片并将其放入堆栈。本质上,它会在每次调用时添加另外 N 张卡片,这可能不是您想要的。
另一个用例:如果同时调用对 "initialize deck" 的两个(或更多)请求怎么办?内部堆栈将包含奇怪的卡片组合...同样,可能不是您的目标。
可以为甲板管理器创建一个 "init" 方法并用 @PostConstruct
注释对其进行注释。在这种方法中,您可以创建一个卡片组,并且不需要 HTTP 方法。 Spring 将在初始化期间恰好调用此方法一次。