Spring未加@Autowired的构造函数为何被调用且先于@Autowired方法执行
问题原因解析
构造函数未加@Autowired却被自动调用的原因
- 首先看你的
Person类代码:你只显式定义了一个接收Name、Emotion两个参数的有参构造,没有写无参构造。按照Java语法规则,只要类里显式定义了任意构造函数,编译器就不会自动生成默认的无参构造,也就是说你的Person类实际上只有这一个构造函数可用。 - 从Spring 4.3版本开始,对于IOC容器管理的Bean,只要类中仅存在一个有参构造函数,不需要手动给构造函数加
@Autowired注解,Spring就会默认选择这个构造函数来实例化Bean,同时自动从容器中找到类型匹配的依赖对象作为构造参数传入。这就是你观察到构造函数被自动触发的核心原因,属于Spring提供的默认特性,不是异常现象。
构造函数早于@Autowired标注方法执行的原因
这个执行顺序是Java对象创建规则和Spring Bean生命周期的固定逻辑决定的,没有任何特殊处理:
- 从Java基础逻辑来说,要生成一个类的对象实例,第一步必须先调用构造函数在内存中开辟空间、生成实例对象,只有对象真实存在之后,才能调用这个对象的方法、给对象的属性赋值。根本不存在“对象还没创建就先调用它的setter方法”的可能。
- 从Spring Bean的创建流程来说,固定执行顺序是:解析Bean定义 → 选择构造函数完成对象实例化(这一步就会执行构造函数内的所有逻辑)→ 进入属性填充阶段,处理字段、setter方法上的
@Autowired注解,注入对应依赖 → 后续执行初始化回调等其他逻辑。你加了@Autowired的setName、setEmotion方法都属于属性填充阶段的执行逻辑,自然会晚于实例化阶段的构造函数执行。
额外说明:从你的运行日志也能看出来,构造函数已经给
name和emotion属性赋过一次值,后续属性填充阶段Spring又调用了两次set方法把属性重新赋值了一遍,所以最终对象里存储的是set注入覆盖后的值,和你最后打印的toString结果完全匹配。如果不需要重复赋值,要么保留构造注入去掉setter上的@Autowired,要么补上无参构造只用setter注入即可。
内容的提问来源于stack exchange,提问作者CoreDevilSon
相关产品推荐
相关产品推荐

