【发布时间】:2022-01-26 08:46:21
【问题描述】:
我正在开发一个 Spring Boot 项目,但在尝试自动装配服务时遇到了一些问题。这是我当前的代码:
@Component
public class StealFromPocket implements Command {
private Integer gameId;
private Player playerFrom;
@Autowired
GameService gameService;
public StealFromPocket(Integer gameId, Player playerFrom) {
this.gameId = gameId;
this.playerFrom = playerFrom;
}
@Override
public void execute() {
gameService.findPlayersByGameId(gameId).forEach(player -> {
new StealCoinCommand(playerFrom, player).execute();
});
}
}
构造函数参数gameId 和playerFrom 在运行时是已知的,因此我无法对它们进行硬编码或将它们存储在配置文件中。
这是 StealFromPocket 通过反射从 service 实例化的地方(completeClassName 将根据用户交互而变化。在本例中,它将是 org.springframework...StealFromPocket:
Class<?> clazz = Class.forName(completeClassName);
Object card = clazz.getDeclaredConstructor(Integer.class, Player.class).newInstance(gameId, playerFrom);
Method method = clazz.getDeclaredMethod("execute");
method.invoke(card);
在尝试构建项目时,我收到以下错误:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in org.springframework.ntfh.cardlogic.abilitycard.rogue.RobarBolsillos required a bean of type 'java.lang.Integer' that could not be found.
Action:
Consider defining a bean of type 'java.lang.Integer' in your configuration.
我认为问题在于我没有将GameService 作为构造函数参数传递,但由于我的项目的性质,这些服务不能作为参数传递,因为它们会根据通过反射实例化的类而有所不同。
【问题讨论】:
-
你可以在 GameService 中创建一个函数来获取卡片对象,而不是调用“method.invoke”,然后你可以移动到该函数内部的逻辑并在之后调用它,如“gameService.invoke(card)”实例化卡片对象。这允许您删除 Command 类中的 GameService 字段
-
非常感谢您的回答。拥有单独类的目的是解耦这两个组件的逻辑,因为将有大约 50 个类,如
StealFromPocket,每个类都有自己的逻辑和服务依赖项,因此将它们全部放在GameService类中就可以了很大,很难理解。 -
当您尝试使用 new 关键字或通过反射进行实例化时,我不认为 spring 可以注入自动装配的 bean,但您可以尝试从“GameService”字段中删除“@Autowired”,但将其保留为该类中的字段,之后您接受 2 个构造函数参数,即“gameId”和“playerForm”
-
当你调用“newInstance”方法时编译器不应该抱怨实例化,因为“GameService”不再有“@Autowired”并且不在构造函数中,所以你可以在之后从“applicationContext”获取那个bean实例化卡片并调用 "card.setGameService(gameService)" ,您在此对象中设置了 "gameService"。所以你现在可以调用方法调用了。让我知道这是否有效
-
您可能需要将“setGameService”方法添加到您的“Command”接口中
标签: java spring spring-boot constructor autowired