Spring构造注入

   构造注入

     Spring 通过构造方法赋值的能力,称为构造注入。 使用构造注入要为该类添加有参构造函数

     
     
在配置文件中如图:

一个<constructor-arg>元素表示构造方法的一个参数,且使用时不用区分顺序。当构造方法的参数出现混淆,无法区分时,可以通过<constructor-arg>元素的index元素属性指定该参数的位置索引,位置从0开始。

构造注入的时效性好,在对象实列化时就得到所依赖的对象,便于在对象的初始化方法中使用依赖对象


<think>我们正在讨论Spring框架中的构造注入和Setter注入。根据提供的引用,我将整理这两种注入方式的原理、区别及使用场景。 原理: - 构造注入:通过类的构造方法来实现依赖注入。在创建Bean实例时,Spring容器会调用相应的构造器,并传入所需的依赖项作为参数。 - Setter注入:通过类的Setter方法来实现依赖注入。在Bean实例化后,Spring容器会调用Setter方法,将依赖项作为参数传入。 区别: 1. 注入时机: - 构造注入:在对象创建时完成依赖注入,确保对象完全初始化后才可使用。 - Setter注入:在对象创建后,通过调用Setter方法注入依赖,因此对象可能处于部分初始化状态(如果某些依赖未注入)。 2. 依赖不可变性: - 构造注入:通常将依赖声明为`final`,注入后不可变。 - Setter注入:依赖可变,可以在对象生命周期中多次注入(但通常不推荐频繁更改)。 3. 依赖必要性: - 构造注入:强制要求依赖,适用于必需依赖。如果容器无法提供所需的依赖,则创建对象失败。 - Setter注入:适用于可选依赖,允许依赖为`null`(需要谨慎处理空指针异常)。 4. 循环依赖处理: - 构造注入:无法解决构造器级别的循环依赖(Spring会抛出`BeanCurrentlyInCreationException`)。 - Setter注入:可以解决循环依赖,因为Spring先创建对象(通过无参构造器),然后通过Setter注入依赖。 5. 初始化完整性: - 构造注入:保证对象完全初始化,因为依赖在构造时已注入- Setter注入:可能存在部分初始化状态,因为依赖可能未被完全注入。 使用场景: - 构造注入:推荐用于强制依赖(即对象运行所必需的依赖),特别是当依赖不可变时。此外,它保证了对象在创建后立即处于可用状态。 - Setter注入:适用于可选依赖,或者需要动态更改依赖的场景。也适用于解决循环依赖的情况。 另外,根据引用[2]和[3],实际开发中可以结合使用: - 强制依赖使用构造注入:确保必要的依赖在对象创建时就被注入- 可选依赖使用Setter注入:提供灵活性,允许在运行时更改或省略依赖。 注意:如果受控对象没有提供Setter方法,则必须使用构造注入。同时,Spring官方推荐使用构造注入(尤其是在Spring 4.x及以后版本),因为它更安全且能保证不可变性。但具体使用哪种方式,还需根据实际需求灵活选择。 相关问题: 1. 构造注入如何处理循环依赖问题? 2. 在Spring Boot应用中,更推荐使用构造注入还是Setter注入?为什么? 3. 如何配置Spring以同时使用构造注入和Setter注入? </think>### Spring构造注入与Setter注入详解 #### 一、核心原理 1. **构造注入** 通过类构造函数实现依赖注入,在对象创建时强制注入所有必需依赖。 ```java public class UserService { private final UserRepository repo; // final字段保证不变性 public UserService(UserRepository repo) { // 构造注入 this.repo = repo; } } ``` 2. **Setter注入** 通过Setter方法实现依赖注入,允许在对象创建后动态修改依赖。 ```java public class OrderService { private PaymentGateway gateway; // 非final字段 public void setGateway(PaymentGateway gateway) { // Setter注入 this.gateway = gateway; } } ``` #### 二、关键区别 | 特性 | 构造注入 | Setter注入 | |---------------------|------------------------------|-------------------------------| | **注入时机** | 对象创建时强制完成 | 对象创建后可延迟注入 | | **依赖不可变性** | 支持final字段(强制不可变) | 依赖可变(可多次调用Setter) | | **依赖必要性** | 强制要求所有必需依赖 | 支持可选依赖(允许null) | | **初始化完整性** | 对象完全初始化后才可使用 | 可能处于部分初始化状态[^1] | | **循环依赖处理** | 无法解决构造函数循环依赖 | 可通过延迟加载解决循环依赖[^2] | | **代码健壮性** | 避免NPE(依赖不可为空) | 需手动检查空指针风险[^3] | #### 三、使用场景指南 1. **优先使用构造注入** - 强制依赖(如数据库连接、核心服务) - 需要依赖不变性的场景(如并发安全) - Spring Boot官方推荐方式(保证线程安全)[^1] 2. **适用Setter注入的场景** - 可选依赖(如日志服务、配置参数) - 需要动态切换依赖的实现 - 遗留代码(无构造函数可用时) - 解决特定循环依赖问题[^2] 3. **混合使用策略**(推荐实践) ```java public class ProductService { private final InventoryDao dao; // 强制依赖 private DiscountStrategy strategy; // 可选依赖 // 构造注入核心依赖 public ProductService(InventoryDao dao) { this.dao = dao; } // Setter注入可选依赖 public void setStrategy(DiscountStrategy strategy) { this.strategy = strategy; } } ``` #### 四、决策流程图 ``` ┌─────────────┐ │ 依赖是否必需? │ └──────┬──────┘ ┌───────────┴───────────┐ Yes │ │ No ┌────────┴───────┐ ┌───────┴───────┐ │ 需要依赖不可变吗? │ │ 依赖需要动态变更吗?│ └───────┬────────┘ └───────┬───────┘ Yes│ │No Yes│ │No ▼ ▼ ▼ ▼ ┌────────────┐ ┌─────────────┐ ┌──────────┐ ┌──────────┐ │ 构造注入 │ │混合注入 │ │Setter注入 │ │无需注入 │ │ (强制+不可变)│ │(构造器+Setter)│ │(动态依赖) │ │(如常量字段)│ └────────────┘ └─────────────┘ └──────────┘ └──────────┘ ``` > **最佳实践提示**: > - Spring 4.3+ 支持单构造函数的隐式注入(无需`@Autowired`) > - 使用`@Required`注解可强制Setter注入的依赖不为空 > - 避免在Setter注入中修改已初始化的业务状态[^3]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值