Spring Boot求助:@SpringBootApplication无法自动注入Service且抛空指针
解决Spring Boot中@Autowired静态字段为Null的问题
嘿,我一眼就看穿问题所在了——你遇到的NullPointerException根本和scanBasePackages配置无关,核心原因是Spring不支持给静态字段做@Autowired注入!
为什么会这样?
Spring的依赖注入是基于对象实例的,它管理的是一个个Bean实例;而静态字段属于类本身,不属于任何对象实例,所以Spring容器没办法把Bean注入到静态变量里。你看到ThreadPoolTaskExecutor能正常初始化,是因为它是通过@Bean声明的独立Bean,Spring直接管理这个实例,和静态注入完全没关系——你的MyCustomService其实已经被Spring扫描到并创建了,只是静态变量拿不到它而已。
具体解决方案
这里给你两种靠谱的解决办法,按需选择:
方案1:改用非静态字段(推荐)
把静态的myCustomService改成实例字段,然后通过Spring上下文获取App实例来调用方法,或者用@PostConstruct在初始化完成后执行逻辑:
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) public class App{ private static Logger logger = LoggerFactory.getLogger(App.class); @Autowired private MyCustomService myCustomService; // 去掉static修饰符 public static void main(String[] args) { // 获取Spring上下文 ApplicationContext context = SpringApplication.run(App.class, args); // 获取App类的实例 App appInstance = context.getBean(App.class); // 通过实例调用方法 appInstance.callCustomServiceMethod(); } // 可选:用@PostConstruct在Bean初始化完成后自动执行 @PostConstruct private void init() { myCustomService.anyMethod(); } private void callCustomServiceMethod() { myCustomService.anyMethod(); } @Bean public ThreadPoolTaskExecutor jobLauncherTaskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); executor.setMaxPoolSize(20); executor.setQueueCapacity(25); return executor; } }
方案2:静态setter手动注入(应急用,不推荐)
如果一定要保留静态字段,可以添加一个带@Autowired的非静态setter方法,让Spring调用它来给静态变量赋值:
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) public class App{ private static Logger logger = LoggerFactory.getLogger(App.class); private static MyCustomService myCustomService; // Spring会自动调用这个setter方法注入实例 @Autowired public void setMyCustomService(MyCustomService service) { App.myCustomService = service; } public static void main(String[] args) { SpringApplication.run(App.class, args); // 注意:必须等Spring上下文完全初始化后再调用,否则可能还是null myCustomService.anyMethod(); } @Bean public ThreadPoolTaskExecutor jobLauncherTaskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); executor.setMaxPoolSize(20); executor.setQueueCapacity(25); return executor; } }
额外说明:关于scanBasePackages
其实你的项目结构完全不需要配置scanBasePackages——@SpringBootApplication默认会扫描当前类所在的包(com.project.name)及其所有子包,com.project.name.service是它的子包,所以你的MyCustomService早就被Spring扫描到了,注释掉scanBasePackages完全没问题。
内容的提问来源于stack exchange,提问作者Genaut
相关产品推荐
相关产品推荐

