SpringBoot普通类调用Repository保存实体报空指针异常解决方案
问题原因
空指针的核心原因有两个:
- 你手动用
new MovieImport()创建实例,这个对象不归Spring容器管理:所有标注了@Service、@RestController、@Repository的类,只有被Spring容器初始化、托管时,它声明的依赖才会被自动注入。你自己new出来的对象是脱离容器的独立实例,哪怕加了@Autowired注解也不会生效。 - 你给
MovieImport定义了需要传入MovieRepository的有参构造方法,但是new实例的时候调用的是不存在的无参构造,相当于movieRepository字段根本没有被赋值,自然调用save方法时会报空指针。
你在RestController里能正常用,是因为Controller是Spring启动时自动扫描创建的托管Bean,内部的Repository已经完成注入,不需要你手动new。
修复方案
不要手动new@Service标注的类实例,直接从Spring容器获取已经完成依赖注入的Bean来调用即可,启动后执行逻辑用SpringBoot提供的CommandLineRunner是最规范的写法,修改启动类代码如下:
package com.domain.springboot; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import com.domain.springboot.services.MovieImport; @SpringBootApplication public class InfMApplication implements CommandLineRunner { // 注入Spring容器已经初始化好的MovieImport实例,其内部的MovieRepository已经完成注入 @Autowired private MovieImport movieImport; public static void main(String[] args) { SpringApplication.run(InfMApplication.class, args); } @Override public void run(String... args) throws Exception { // 容器启动完成后自动执行该方法,直接调用业务逻辑即可 movieImport.main(); } }
注意事项
- 所有被
@Component、@Service、@Repository、@RestController等Spring注解标记的托管类,禁止手动通过new关键字创建实例,否则所有依赖注入逻辑都不会生效,必然出现空指针。 - 你原启动类中直接调用
movieImport.saveToDb()不符合方法定义,该方法需要传入Movie类型参数,直接调用你在MovieImport中写的main()方法即可走完随机拉取电影、获取详情、存入数据库的全流程。 - 如果后续确实需要在完全脱离Spring管理的普通类中使用托管Bean,可以实现一个Spring上下文工具类获取对应Bean,但你当前的启动初始化场景用
CommandLineRunner是SpringBoot官方推荐的标准写法,不需要额外编写冗余代码。
内容的提问来源于stack exchange,提问作者Luca K.
相关产品推荐
相关产品推荐

