Grails领域类注入ElasticsearchService出现空对象错误如何解决
问题根因
你遇到的空指针问题不是拼写错误导致的,是默认配置下GORM领域类不会自动装配Spring托管的Bean,你声明的elasticsearchService属性没有被Spring容器注入实例,因此调用方法时为空。
手动实例化服务会丢失事务支持的原因是,只有Spring容器托管的Bean,才会自动处理@Transactional注解的切面逻辑,你自己new的实例没有经过Spring的代理增强,自然不支持事务。
可行的解决方案(无需手动实例化)
不需要一直用手动实例化的写法,有几种更合理的方案:
- 方案1:开启全局领域类自动注入
在项目配置文件application.yml中添加如下配置,开启领域类的自动装配能力:
配置生效后你原本的依赖注入写法就能正常工作,服务的事务能力也会保留。grails: gorm: autowire: true - 方案2:用Holders手动获取Spring托管的服务实例
如果不想开启全局自动注入,可以在事件方法内通过Spring上下文直接获取已经托管的服务实例,事务能力不会丢失:import grails.util.Holders def afterInsert() { def elasticsearchService = Holders.grailsApplication.mainContext.getBean(ElasticsearchService) elasticsearchService.save(this) } - 方案3:用GORM事件监听器解耦逻辑
更符合分层规范的写法是将ES同步逻辑抽离到独立的事件监听器中,在监听器内注入服务处理,避免领域类和业务服务耦合:@Component class DocumentESOListener implements ApplicationListener<AfterInsertEvent<DocumentESO>> { ElasticsearchService elasticsearchService @Override void onApplicationEvent(AfterInsertEvent<DocumentESO> event) { elasticsearchService.save(event.entity) } }
内容的提问来源于stack exchange,提问作者boraas
相关产品推荐
相关产品推荐

