news 2026/1/3 18:10:57

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/1/2 9:25:34

电源管理设计:超详细版硬件电路指南

电源管理设计:从理论到实战的硬件电路全解析在现代电子系统中,一个看似简单的“供电”问题,背后往往藏着复杂的工程权衡。你有没有遇到过这样的情况:电路板焊接完成、程序烧录无误,结果系统却频频重启?或者…

作者头像 李华
网站建设 2026/1/3 17:27:48

技术直播主题策划:五场带你玩转TensorRT系列课程

五场直播带你深入掌握TensorRT:从优化原理到工业级部署 在AI模型越来越“重”的今天,一个训练好的视觉模型动辄几百MB甚至上GB,推理延迟动不动就几十毫秒——这样的表现显然无法满足实时视频分析、自动驾驶决策或高并发云端服务的需求。我们…

作者头像 李华
网站建设 2026/1/2 7:34:28

hbuilderx下载完整示例:模拟课堂环境的一键部署方案

用 HBuilderX 一键下载完整示例,打造高效稳定的模拟课堂环境你有没有遇到过这样的场景?一节前端开发实训课开始前,老师站在讲台上喊:“同学们先把开发工具装好,Node.js 装了吗?HBuilderX 下载了吗&#xff…

作者头像 李华
网站建设 2026/1/3 13:25:43

客户成功案例库建设:积累真实有效的口碑资产

TensorRT:解锁AI推理性能的钥匙与客户口碑资产构建 在当今AI技术加速落地的时代,一个模型能否真正“跑得起来”,往往不在于它在论文中的准确率有多高,而在于它上线后能不能扛住真实流量、满足毫秒级响应要求。我们见过太多项目——…

作者头像 李华
网站建设 2026/1/2 5:02:16

售前技术支持话术整理:解答关于性能的十大疑问

售前技术支持话术整理:解答关于性能的十大疑问 在AI模型从实验室走向产线的过程中,一个反复被客户问到的问题是:“为什么我的模型跑得这么慢?明明参数量也不大。” 更有客户直言:“我们已经上了GPU,怎么还是…

作者头像 李华
网站建设 2026/1/2 8:18:03

国际化拓展策略:TensorRT在全球市场的本地化适配

国际化拓展策略:TensorRT在全球市场的本地化适配 在跨国AI系统部署中,企业常面临“性能悬崖”现象——同一模型在德国数据中心延迟为120ms,而在新加坡节点却飙升至380ms。这种波动源于硬件架构、数据特征和合规要求的区域差异。NVIDIA Tensor…

作者头像 李华