news 2026/6/9 21:19:40

Spring Boot 依赖注入指南:多种方式深度剖析与代码演示

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Boot 依赖注入指南:多种方式深度剖析与代码演示

在Spring Boot中,依赖注入是一项核心特性,它有助于创建松散耦合的应用程序。

1. 构造函数注入

构造函数注入通过类的构造函数来传递依赖。这确保了在对象创建时,依赖就已经准备好,并且不可变。如果一个类的依赖在其整个生命周期内都不会改变,构造函数注入是一个很好的选择。它还能帮助确保依赖不为空,因为构造函数参数通常是必需的。

示例代码

假设我们有一个UserService依赖于UserRepository

首先定义UserRepository接口和实现类:

importorg.springframework.stereotype.Repository;@RepositorypublicclassUserRepository{publicvoidsaveUser(Stringuser){System.out.println("Saving user: "+user);}}

然后定义UserService,通过构造函数注入UserRepository

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;@ServicepublicclassUserService{privatefinalUserRepositoryuserRepository;@AutowiredpublicUserService(UserRepositoryuserRepository){this.userRepository=userRepository;}publicvoidregisterUser(Stringuser){userRepository.saveUser(user);}}

在Spring Boot中,@Autowired注解并非必需,如果构造函数只有一个,Spring会自动进行依赖注入。上述代码可以简化为:

importorg.springframework.stereotype.Service;@ServicepublicclassUserService{privatefinalUserRepositoryuserRepository;publicUserService(UserRepositoryuserRepository){this.userRepository=userRepository;}publicvoidregisterUser(Stringuser){userRepository.saveUser(user);}}

2. Setter方法注入

Setter方法注入通过调用Setter方法来设置依赖。这种方式更加灵活,因为可以在对象创建后再设置依赖。适用于依赖在对象创建时可能不可用,或者依赖可能在对象的生命周期内发生变化的情况。

示例代码

同样基于前面的UserRepository,定义使用Setter注入的UserService

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;@ServicepublicclassUserService{privateUserRepositoryuserRepository;@AutowiredpublicvoidsetUserRepository(UserRepositoryuserRepository){this.userRepository=userRepository;}publicvoidregisterUser(Stringuser){userRepository.saveUser(user);}}

3. 字段注入(属性注入)

字段注入直接在类的字段上使用注解来注入依赖。这种方式代码简洁,但不利于单元测试,因为难以在测试中替换依赖。

示例代码
importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;@ServicepublicclassUserService{@AutowiredprivateUserRepositoryuserRepository;publicvoidregisterUser(Stringuser){userRepository.saveUser(user);}}

4. 基于Java配置类的依赖注入

在Spring Boot中,除了使用组件扫描和自动装配,还可以通过Java配置类来手动配置Bean及其依赖关系。这种方式在需要更精细控制Bean的创建和配置时非常有用。

示例代码

首先创建一个Java配置类AppConfig

importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;@ConfigurationpublicclassAppConfig{@BeanpublicUserRepositoryuserRepository(){returnnewUserRepository();}@BeanpublicUserServiceuserService(UserRepositoryuserRepository){returnnewUserService(userRepository);}}

然后可以在其他组件中使用UserService,Spring会根据配置类来注入依赖。

5. 基于注解驱动的条件注入

有时候,我们可能希望根据某些条件来决定是否注入某个依赖。Spring Boot提供了基于注解的条件注入方式,如@Conditional注解及其变体。

示例代码

假设我们有一个DatabaseConfig类,根据系统属性来决定是否创建DataSource

importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Conditional;importorg.springframework.context.annotation.Configuration;importjavax.sql.DataSource;importorg.apache.tomcat.jdbc.pool.DataSourceasTomcatDataSource;@ConfigurationpublicclassDatabaseConfig{@Value("${use.in.memory.database:false}")privatebooleanuseInMemoryDatabase;@Bean@Conditional(InMemoryDatabaseCondition.class)publicDataSourceinMemoryDataSource(){TomcatDataSourcedataSource=newTomcatDataSource();dataSource.setUrl("jdbc:h2:mem:testdb");dataSource.setDriverClassName("org.h2.Driver");dataSource.setUsername("sa");dataSource.setPassword("password");returndataSource;}@Bean@Conditional(ProductionDatabaseCondition.class)publicDataSourceproductionDataSource(){TomcatDataSourcedataSource=newTomcatDataSource();dataSource.setUrl("jdbc:mysql://localhost:3306/productiondb");dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");dataSource.setUsername("root");dataSource.setPassword("password");returndataSource;}}

这里定义了两个DataSource的Bean,inMemoryDataSourceproductionDataSource,分别基于不同的条件进行创建。@Conditional注解的参数是一个实现了Condition接口的类,通过实现matches方法来定义条件逻辑。例如:

importorg.springframework.context.annotation.Condition;importorg.springframework.context.annotation.ConditionContext;importorg.springframework.core.type.AnnotatedTypeMetadata;publicclassInMemoryDatabaseConditionimplementsCondition{@Overridepublicbooleanmatches(ConditionContextcontext,AnnotatedTypeMetadatametadata){returncontext.getEnvironment().getProperty("use.in.memory.database",Boolean.class,false);}}
importorg.springframework.context.annotation.Condition;importorg.springframework.context.annotation.ConditionContext;importorg.springframework.core.type.AnnotatedTypeMetadata;publicclassProductionDatabaseConditionimplementsCondition{@Overridepublicbooleanmatches(ConditionContextcontext,AnnotatedTypeMetadatametadata){return!context.getEnvironment().getProperty("use.in.memory.database",Boolean.class,false);}}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 9:07:54

LVGL移植深度剖析:从底层驱动到GUI渲染流程

LVGL移植实战全解:从驱动对接到界面流畅渲染的每一步你有没有遇到过这样的场景?手头一块STM32开发板,配上一个SPI接口的ILI9341屏幕,满心欢喜想做个炫酷界面,结果一跑LVGL,不是卡顿就是花屏,触摸…

作者头像 李华
网站建设 2026/6/10 0:50:49

工业传感器数据采集的MDK实战方案

工业传感器数据采集的MDK实战:从硬件接口到RTOS调度的全流程设计在智能制造和工业物联网(IIoT)不断推进的今天,工厂设备早已不再是“哑巴”机器。它们通过遍布各处的工业传感器感知温度、压力、振动、湿度等关键参数,并…

作者头像 李华
网站建设 2026/6/10 10:42:38

白皮书撰写思路:《大模型推理优化技术演进》提纲分享

大模型推理优化技术演进:从 TensorRT 看高性能部署的工程实践 在大模型落地进入深水区的今天,一个现实问题摆在每个 AI 工程师面前:我们能训练出千亿参数的语言模型,但用户不会为“能跑”买单——他们要的是秒回、是流畅、是稳定。…

作者头像 李华
网站建设 2026/6/10 10:40:50

keil5安装包下载后在工控HMI开发中的初步应用

从零开始搭建工控HMI开发环境:Keil5实战全解析在工业自动化现场,你是否曾见过这样的场景——操作员轻触屏幕,产线状态实时跳动;报警弹窗瞬间弹出,响应毫秒级触发。这背后,往往离不开一个稳定高效的嵌入式开…

作者头像 李华
网站建设 2026/6/9 17:10:44

Multisim主数据库多工程师协作管理:最佳实践

Multisim主数据库多工程师协作管理:从混乱到规范的实战指南在一家中型通信设备公司,新入职的硬件工程师小李接到任务:为新一代电源模块设计一个Buck-Boost电路。他打开Multisim,准备调用TI的一款DC-DC芯片,却发现库里没…

作者头像 李华
网站建设 2026/6/9 18:30:47

STM32使用HAL库实现USB协议:项目应用实例

STM32用HAL库玩转USB通信:从零实现虚拟串口实战指南你有没有遇到过这样的场景?设备已经调通了传感器和算法,结果卡在“怎么把数据传给PC”这一步——串口线太短、蓝牙配对失败、Wi-Fi功耗太高……最后只能接个串口转USB模块,多一块…

作者头像 李华