无Spring Boot启动Spring项目,解决@Autowired注入为空问题
问题描述
我是Spring零基础学习者,原本使用Spring Boot能成功运行简单项目,为深入理解IoC和依赖注入,尝试脱离Spring Boot启动项目。但直接通过new创建TestSpringApplication实例并调用run方法时,@Autowired注入的messageRepository等对象为空。我猜测是因为未通过ApplicationContext.getBean()获取Bean,但不知道如何在静态main方法中获取ApplicationContext。
以下是尝试的非Boot版本代码(无法运行)和之前可用的Boot版本代码:
非Boot版本代码(无法运行)
package com.cypherf; import com.cypherf.model.Message; import com.cypherf.repository.MessageRepository; import com.cypherf.service.MessageService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan public class TestSpringApplication { @Autowired private ApplicationContext context; @Autowired private MessageRepository messageRepository; @Autowired private MessageService messageService; public static void main(String[] args) { TestSpringApplication app = new TestSpringApplication(); app.run(args); } public void run(String... args) { messageRepository.save(new Message("Message one")); messageRepository.save(new Message("Message two")); messageRepository.save(new Message("Message two")); messageService.printAllMessages(); } }
Boot版本代码(可运行)
package com.cypherf; import com.cypherf.model.Message; import com.cypherf.repository.MessageRepository; import com.cypherf.service.MessageService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class TestSpringApplication implements CommandLineRunner { @Autowired private MessageRepository messageRepository; @Autowired private MessageService messageService; public static void main(String[] args) { SpringApplication.run(TestSpringApplication.class, args); } public void run(String... args) throws Exception { messageRepository.save(new Message("Message one")); messageRepository.save(new Message("Message two")); messageRepository.save(new Message("Message two")); messageService.printAllMessages(); } }
问题原因
直接通过new创建的TestSpringApplication对象不属于Spring容器管理的Bean,Spring不会对这个对象执行依赖注入,因此@Autowired标注的属性都会是null。必须先初始化Spring容器,获取ApplicationContext,再从容器中获取Bean实例,才能让依赖注入生效。
修正方案
在静态main方法中,使用AnnotationConfigApplicationContext初始化Spring容器,加载你的配置类(TestSpringApplication本身就是@Configuration类),然后从容器中获取TestSpringApplication的Bean实例,再调用run方法。
修正后的非Boot版本代码:
package com.cypherf; import com.cypherf.model.Message; import com.cypherf.repository.MessageRepository; import com.cypherf.service.MessageService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan public class TestSpringApplication { @Autowired private MessageRepository messageRepository; @Autowired private MessageService messageService; public static void main(String[] args) { // 初始化Spring容器,加载配置类 ApplicationContext context = new AnnotationConfigApplicationContext(TestSpringApplication.class); // 从容器中获取TestSpringApplication的Bean实例 TestSpringApplication app = context.getBean(TestSpringApplication.class); app.run(args); } public void run(String... args) { messageRepository.save(new Message("Message one")); messageRepository.save(new Message("Message two")); messageRepository.save(new Message("Message two")); messageService.printAllMessages(); } }
补充说明
AnnotationConfigApplicationContext是Spring核心容器的实现类,用于基于Java配置类初始化容器。- 只有从Spring容器中获取的Bean实例,Spring才会自动完成依赖注入,
@Autowired等注解才会生效。 - 如果需要在Bean内部获取
ApplicationContext,可以让类实现ApplicationContextAware接口,Spring会自动注入容器实例,无需手动@Autowired。
内容的提问来源于stack exchange,提问作者Gaetan L.
相关产品推荐
相关产品推荐

