Spring框架中构造函数注入DataService的底层原理及装配含义
问题背景与代码示例
我正在学习Java语言的工作机制,基于Spring框架定义了DataService接口作为MongoDB和MySQL数据库服务的交互接口,相关代码如下:
DataService.java
public interface DataService { int[] retrieveData(); // 从不同数据库获取数据的方法 }
MongoDbDataService.java
@Component public class MongoDbDataService implements DataService { public int[] retrieveData() { return new int[] {11, 22, 33, 44, 55}; } }
MySQLDataService.java
@Component @Primary public class MySQLDataService implements DataService { public int[] retrieveData() { return new int[] {1,2,3,4,5}; } }
BusinessCalculationService.java
@Component public class BusinessCalculationService { private DataService dataService; public BusinessCalculationService(DataService dataService) { this.dataService = dataService; } public int findMax() { return Arrays.stream(dataService.retrieveData()).max().orElse(0); } }
核心疑问
- 上述构造函数在编译/执行时,后台究竟发生了什么?
public BusinessCalculationService(DataService dataService) { this.dataService = dataService; }
DataService对象是如何与BusinessCalculationService“绑定”或“装配(wired)”的?- “装配(wired)”又是什么意思?
问题解答
一、构造函数执行时的后台流程
Spring应用启动时,会按以下步骤处理:
- 组件扫描:Spring会遍历项目中所有标注了
@Component(包括@Service、@Repository等衍生注解)的类,把MongoDbDataService、MySQLDataService、BusinessCalculationService都标记为需要由Spring容器管理的Bean。 - 依赖解析:Spring识别到
BusinessCalculationService的构造函数需要一个DataService类型的对象,会先处理这个依赖的实例化。 - 实例选择:因为
DataService有两个实现类,而MySQLDataService标注了@Primary,Spring会优先选择它的实例作为注入目标。 - 构造注入执行:Spring先创建
MySQLDataService的实例(如果还没创建),然后调用BusinessCalculationService的构造函数,把MySQLDataService实例作为参数传入,完成BusinessCalculationService的实例化,最后把这个实例存入Spring容器。 - 后续可用:当你从Spring容器中获取
BusinessCalculationService实例时,它内部的dataService成员变量已经是预先注入好的MySQLDataService对象了。
二、DataService与BusinessCalculationService的绑定/装配过程
这是Spring构造器依赖注入的典型流程:
- Spring容器初始化
BusinessCalculationService之前,会先解析它的构造函数参数类型(DataService),然后在容器中查找所有匹配该类型的Bean。 - 借助
@Primary注解的优先级,Spring确定使用MySQLDataService的实例作为依赖。 - 最后通过调用构造函数,把
MySQLDataService实例传递给BusinessCalculationService,完成绑定——此时BusinessCalculationService内部的dataService就指向了MySQLDataService的实例,后续调用findMax()时会直接使用该实例的retrieveData()方法。
三、“装配(wired)”的含义
在Spring语境里,“装配(wired)”就是依赖注入(DI)的通俗说法,指Spring容器自动将一个Bean的依赖对象(比如这里的DataService实例)注入到需要它的Bean(比如BusinessCalculationService)中的过程。简单说就是Spring帮你自动建立组件间的依赖关系,不用手动new依赖对象,实现了组件的解耦。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

