Grails 4普通Service无法注入到Data Service中导致运行时NPE问题求助
这个问题我之前也碰到过,核心原因是Grails 4中GORM自动生成的Data Service实现类,默认不会自动注入普通的Spring Bean(也就是你这种没有关联领域模型的自定义Service)。虽然你的MessagingService在grails-app/services目录下会被Spring管理,但动态生成的FlowService实现并不会自动处理这个属性的注入,所以才会出现NPE。
下面给你两种官方推荐的正确解决方式:
方法1:使用@Autowired显式注入
直接在FlowService的messagingService属性上添加Spring的@Autowired注解,告诉Spring要主动注入这个Bean:
import org.springframework.beans.factory.annotation.Autowired class MessagingService { def sendEmail(String message) { // 你的邮件发送逻辑 } } interface IFlowService { void sendFoo(String message) } @Service(Flow) abstract class FlowService implements IFlowService { @Autowired MessagingService messagingService void sendFoo(String message) { messagingService.sendEmail(message) } }
方法2:构造函数注入(Spring推荐方式)
用构造函数注入的方式,不仅能确保依赖在实例化时就被注入,还能从根源避免空指针的潜在风险:
class MessagingService { def sendEmail(String message) { // 你的邮件发送逻辑 } } interface IFlowService { void sendFoo(String message) } @Service(Flow) abstract class FlowService implements IFlowService { final MessagingService messagingService FlowService(MessagingService messagingService) { this.messagingService = messagingService } void sendFoo(String message) { messagingService.sendEmail(message) } }
为什么临时方案能生效?
你之前在Bootstrap里调用MessagingService的方法,其实是触发了Spring初始化这个Bean,然后手动赋值给FlowService的属性——但这是个临时hack,一旦FlowService的实例被重新创建(比如容器刷新场景),又会回到NPE的问题,所以不推荐长期使用。
补充说明
Grails官方文档里其实明确提到:Data Service(标注@Service的抽象类)中可以注入其他Spring Bean,但需要显式使用@Autowired或者构造函数注入。因为动态生成的实现类会继承抽象类的注解,Spring会据此处理依赖注入。普通Grails Service可以自动按名称注入,但Data Service因为是动态生成的,必须显式声明注入规则。
内容的提问来源于stack exchange,提问作者sodastream

