Spring Boot 应用启动时,被 @Service、@RestController 或 @Configuration 等注解标记的类作为 Spring Bean,其构造函数会在容器初始化该单例 Bean 时立即执行,通常发生在应用上下文刷新(ApplicationContext refresh)阶段。
spring boot 应用启动时,被 `@service`、`@restcontroller` 或 `@configuration` 等注解标记的类作为 spring bean,其构造函数会在容器初始化该单例 bean 时立即执行,通常发生在应用上下文刷新(applicationcontext refresh)阶段。
在 Spring Boot 中,所有通过组件扫描(如 @ComponentScan)发现并标注了 @Service、@RestController、@Repository、@Configuration 等 stereotype 注解的类,都会被 Spring IoC 容器识别为受管 Bean。默认作用域为 singleton,即整个应用生命周期内仅创建一个实例——而该实例的构造函数,正是在 Bean 实例化阶段被 Spring 容器调用执行的。
以你提供的 MessageController 为例:
@RestController
@RequestMapping("/api/v1")
public class MessageController {
private final RabbitMQProducer producer; // 推荐使用 final 字段保证不可变性
public MessageController(RabbitMQProducer producer) {
this.producer = producer; // 构造函数注入:此处即为 Bean 创建时的执行点
System.out.println("MessageController 构造函数已执行,producer = " + producer);
}
@GetMapping("/publish")
public ResponseEntity<String> sendMessage(@RequestParam("message") String message) {
producer.sendMessage(message);
return ResponseEntity.ok("message sent to the rabbitmq");
}
}✅ 关键执行时机说明:
- 当 Spring Boot 应用调用 SpringApplication.run(...) 启动后,容器进入 refresh() 流程;
- 在 AbstractApplicationContext#refresh() 的 finishBeanFactoryInitialization() 阶段,容器会预实例化所有非懒加载(@Lazy(false) 或默认)的 singleton Bean;
- 此时 MessageController 的构造函数被调用,同时 Spring 自动完成依赖解析:若 RabbitMQProducer 也是 singleton Bean(如标注 @Service),它将先于或同步于 MessageController 被实例化,并作为参数传入构造函数——这正是构造器注入(Constructor Injection)的标准行为。
⚠️ 注意事项:
- 若 RabbitMQProducer 尚未定义为 Bean(如缺少 @Service / @Component 注解,或未被扫描到),启动时将抛出 UnsatisfiedDependencyException,而非运行时错误;
- 构造函数中避免执行耗时操作或外部资源初始化(如连接 RabbitMQ、读取大文件等),因这会阻塞容器启动;推荐将此类逻辑移至 @PostConstruct 方法或实现 InitializingBean 接口;
- 使用 final 修饰依赖字段(如示例所示),既符合不可变设计原则,也明确表达“该依赖必须通过构造注入”,提升代码可测试性与安全性。
? 总结:Spring Boot 中,构造函数不是由开发者显式调用,而是由容器在 Bean 生命周期的“实例化(Instantiation)”阶段自动触发——理解这一时机,是掌握依赖注入本质与排查启动失败问题的关键基础。


















