
在 spring 应用中,将 `dataservice` 实例传入 `businesscalculationservice` 构造函数,本质是将一个已由 spring 容器管理的 bean 引用赋值给类的成员变量;真正的“连接”(wiring)发生在容器启动时的依赖解析与实例化阶段,而非构造函数语句本身。
当你写下如下构造函数:
public BusinessCalculationService(DataService dataService) {
this.dataService = dataService;
}从 Java 语言层面看:这行代码本身不涉及任何“魔法”——它只是执行一次引用赋值操作(reference assignment)。dataService 是一个形参,类型为接口 DataService;当构造函数被调用时,实参(一个实现了 DataService 的对象,如 MySQLDataService 或 MongoDbDataService 的实例)的引用被复制并赋给 this.dataService 字段。此时,BusinessCalculationService 实例持有了对目标服务对象的引用,后续可通过该引用来调用 retrieveData() 等方法。
⚠️ 注意:这里传递的是对象引用,不是对象副本,也不是深拷贝。Java 中所有非基本类型参数都是按值传递(pass-by-value),但该“值”本身是一个指向堆内存中对象的引用地址。
而真正的“自动装配”(auto-wiring)发生在 Spring 容器内部:
立即学习“Java免费学习笔记(深入)”;
- Spring 启动时会扫描所有 @Component、@Service 等注解标记的类,并将其注册为 Bean(即受容器管理的对象实例);
- 对于 @Primary 标记的 MySQLDataService,Spring 将其识别为 DataService 类型的首选实现;
- 当容器需要创建 BusinessCalculationService Bean 时,它会检查其构造函数参数类型(DataService),然后在已注册的 Bean 中查找匹配类型——由于 MySQLDataService 是 @Primary,且 MongoDbDataService 虽也实现 DataService 但未标注优先级,Spring 便唯一确定地选择 MySQLDataService 实例,并将其作为实参传入构造函数;
- 这个过程称为 constructor-based dependency injection(基于构造函数的依赖注入),是 Spring 推荐的强制依赖声明方式。
✅ 正确理解的关键点:
- this.dataService = dataService; 只是普通赋值,无框架行为;
- “Wiring” 指的是 Spring 容器在运行时自动完成依赖匹配 + 实例注入的整套流程;
- 若存在多个 DataService 实现且均未标 @Primary,Spring 会抛出 NoUniqueBeanDefinitionException;
- 若没有 DataService 实现类被 Spring 扫描到,则抛出 NoSuchBeanDefinitionException。
? 小结:构造函数是依赖的“接收入口”,而 Spring 容器是背后的“调度中心”。你写的代码定义了 需要什么(what),Spring 负责决定 提供哪个(which)并在合适时机 如何交付(how)。这种解耦设计正是 Spring IoC(控制反转)的核心价值所在。










