news 2026/5/27 14:28:22

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/5/22 1:28:33

STM32CubeMX中文汉化实操记录:适合入门者的完整示例

手把手教你实现 STM32CubeMX 中文界面:从零开始的汉化实战你有没有过这样的经历?刚打开 STM32CubeMX,面对满屏英文菜单:“Pinout & Configuration”、“Clock Configuration”、“Power Consumption Calculator”……一个个术…

作者头像 李华
网站建设 2026/5/26 10:55:49

多版本Keil共存实战:C51和MDK协同安装完整示例

多版本Keil共存实战:C51与MDK协同安装深度指南 在嵌入式开发的日常中,你是否曾遇到这样的窘境——手头既要维护一个老旧但仍在产的8051项目,又要同步推进基于STM32的新产品设计?打开电脑,却发现Keil只能“二选一”&am…

作者头像 李华
网站建设 2026/5/20 19:46:58

合作伙伴计划设计:联合ISV共同推广TensorRT解决方案

合作伙伴计划设计:联合ISV共同推广TensorRT解决方案 在AI应用从实验室走向真实生产环境的今天,一个模型能否“跑得快、压得省、稳得住”,往往比它在训练集上的准确率更能决定其商业价值。尤其是在医疗影像诊断、工业质检流水线、智能客服响应…

作者头像 李华
网站建设 2026/5/26 9:09:35

基于PLC替代设计的STM32CubeMX安装详解

用STM32打造“软PLC”?先搞定这个开发神器的安装! 你有没有遇到过这样的项目需求:客户想要一个小型自动化控制器,功能类似PLC——读输入、控输出、走通信、跑定时任务。但预算有限,又希望有更强的灵活性和扩展性&…

作者头像 李华
网站建设 2026/5/23 3:27:37

JLink烧录操作指南:从零实现STM32程序下载

JLink烧录实战指南:手把手教你把程序“灌”进STM32 你有没有遇到过这样的场景? 代码写得飞起,编译顺利通过,结果一烧录——“No target connected”。 或者好不容易连上了,Flash下载却失败,提示“Could …

作者头像 李华
网站建设 2026/5/26 3:35:41

高校合作项目申报:借助TensorRT申请产学研基金

高校合作项目申报:借助TensorRT申请产学研基金 在当前人工智能技术加速落地的背景下,高校科研团队面临的挑战早已不止于“模型是否训练出来”,而是转向更现实的问题——这个模型能不能跑得快、压得小、稳得住? 尤其是在申报产学研…

作者头像 李华