news 2026/4/3 4:53:44

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/3/31 7:39:34

小红书种草文案写作:让非技术用户也想试试AI加速

小红书种草文案写作:让非技术用户也想试试AI加速 你有没有发现,最近在小红书刷穿搭、美妆内容时,系统总能“神准”地推荐你喜欢的风格?拍一张照片上传,几秒钟内就能识别出衣服款式、颜色搭配,甚至自动关联相…

作者头像 李华
网站建设 2026/3/7 4:09:34

STM32驱动蜂鸣器电路常见问题:深度解析

STM32驱动蜂鸣器为何总出问题?一文讲透底层原理与实战避坑你有没有遇到过这种情况:明明代码写得没问题,GPIO一拉高,蜂鸣器却“哼”一声就哑了;或者每次响完,MCU莫名其妙复位,调试器都连不上&…

作者头像 李华
网站建设 2026/3/31 13:21:14

keil编译器下载v5.06环境下多任务调度器实现完整指南

在Keil MDK 5.06环境下构建轻量级多任务调度器:从零实现与实战优化当嵌入式系统“忙不过来”时,我们该怎么办?你有没有遇到过这样的场景?一个STM32项目里既要读传感器、又要处理串口命令、还得刷新LCD屏幕、偶尔还要闪一下LED做状…

作者头像 李华
网站建设 2026/3/15 12:23:28

私有化部署客户案例:某银行如何用TensorRT节省百万成本

某银行如何用TensorRT节省百万成本:私有化部署的推理优化实践 在金融系统中,一次交易请求背后的AI推理可能决定着千万级资金的安全。某大型商业银行的日均反欺诈检测调用量高达2亿次,任何毫秒级的延迟累积都会直接影响用户体验和风控有效性。…

作者头像 李华
网站建设 2026/3/21 1:49:16

jlink驱动Windows安装指南:从下载到识别完整流程

J-Link驱动Windows安装全攻略:从零开始,一次搞定设备识别与调试连接 你有没有遇到过这样的场景?新买了一块STM32开发板,兴冲冲打开Keil准备下载程序,结果点击“Debug”时弹出一串红字:“No J-Link found.”…

作者头像 李华
网站建设 2026/4/1 21:40:59

【UML】面向对象中类与类之间的关系详解

作为程序员,在学习或使用面向对象编程(OOP)时,类与类之间的关系是一个绕不开的话题。合理地建模类之间的关系,不仅能让代码更清晰,也能显著提升系统的可维护性和扩展性。 文章目录一、为什么要理解类之间的…

作者头像 李华