为什么Spring不建议使用基于字段的依赖注入?
2 个回答
能轻易失去的东西,我从未觉得重要。大黑牛Spring 不建议使用基于字段的依赖注入(Field Injection),而推荐使用构造函数注入或基于 setter 的注入,原因如下: ### 1. **不易测试** 使用字段注入的 Bean 在单元测试中很难进行依赖的注入,因为测试框架不能直接对私有字段进行注入(除非使用反射工具)。这使得单元测试变得复杂且脆弱,而构造函数注入和 setter 注入则天然支持依赖注入,可以轻松模拟或替换依赖以进行测试。 ### 2. **不利于不可变性** 字段注入通常会导致 Bean 中的依赖在实例化之后仍然可以被修改,破坏了对象的不可变性。而构造函数注入则天然地确保了依赖的不可变性,因为依赖只能在构造时注入,之后不可更改。 ### 3. **违反单一职责原则** 在字段注入中,Bean 自身负责维护依赖的注入,增加了它的职责,使得 Bean 同时负责业务逻辑和依赖管理,增加了耦合度。构造函数注入可以让依赖在对象创建时就完整,明确对象的所有依赖,有助于遵循单一职责原则。 ### 4. **依赖隐式注入** 字段注入依赖于 Spring 的反射机制,使得依赖关系显得隐式化,难以通过类本身的定义清楚地了解它的依赖。而构造函数注入显式声明了依赖,使得依赖关系清晰且易于维护。 ### 5. **影响设计的可读性和可维护性** 构造函数注入可以清晰地标明 Bean 的依赖需求,能使代码更具可读性。当依赖关系增多时,通过构造函数的参数列表可以一目了然地看到 Bean 的依赖。而字段注入则缺乏这种清晰性,增加了维护成本。 ### 6. **潜在的 NPE 问题** 在字段注入的场景中,Bean 的字段可能会在注入之前被使用,容易导致空指针异常(NullPointerException)。而构造函数注入确保所有依赖在对象创建时就已经准备就绪,可以有效避免 NPE。 ### 总结 基于以上原因,Spring 推荐使用构造函数注入,尤其是在现代的 Spring Boot 项目中。构造函数注入可以增强代码的可维护性、可读性、可测试性,同时减少依赖耦合度。发布于 2024-11-04 14:31 •IP属地 海南举报评论收藏
纵然前路迷茫,纵然天隔一方,纵然我手中的刀刃已然破碎,也无法阻挡我寻找你的道路。李枫在讨论依赖注入类型时,先解释一下字段注入的概念会更清晰。下面是依赖注入的三种主要方式,并着重解释字段注入。 ### 依赖注入的三种方式 在 Spring 中,依赖注入有以下三种常见方式: 1. **字段注入(Field Injection)** 2. **构造函数注入(Constructor Injection)** 3. **Setter方法注入(Setter Injection)** ### 1. 字段注入(Field Injection) 字段注入是将依赖直接注入到对象的字段(成员变量)上,通常使用 `@Autowired` 注解在字段上来实现。代码示例如下: ```java @Component public class MyService { @Autowired private DependencyService dependencyService; // 使用 dependencyService 的业务逻辑 } ``` 在字段注入中,Spring 会通过反射将 `DependencyService` 注入到 `MyService` 中的 `dependencyService` 字段。这种方式的代码简洁,减少了写 setter 或构造函数的代码量,但也有一些缺点,如测试困难、无法明确依赖、破坏不可变性等,前面已经提到。 ### 2. 构造函数注入(Constructor Injection) 构造函数注入是通过 Bean 的构造函数来注入依赖。依赖关系通过构造函数的参数传递,使依赖显式可见: ```java @Component public class MyService { private final DependencyService dependencyService; @Autowired public MyService(DependencyService dependencyService) { this.dependencyService = dependencyService; } // 使用 dependencyService 的业务逻辑 } ``` 这种方式的优点是,依赖是不可变的(被声明为 `final`),并且在对象创建时就确定,依赖关系清晰明了,便于测试。 ### 3. Setter 方法注入(Setter Injection) Setter 方法注入是通过 Bean 的 setter 方法来注入依赖。通常在 setter 方法上使用 `@Autowired` 注解来标记注入点: ```java @Component public class MyService { private DependencyService dependencyService; @Autowired public void setDependencyService(DependencyService dependencyService) { this.dependencyService = dependencyService; } // 使用 dependencyService 的业务逻辑 } ``` Setter 方法注入允许依赖是可选的(可以不注入),并且可以在运行时更改依赖。缺点是会导致依赖的可变性,不适合强依赖的情况。 ### 为什么不推荐字段注入? 字段注入虽然简洁,但如前所述,它会导致以下问题: - **不易测试**:字段注入通常需要反射来注入依赖,单元测试变得复杂。 - **不利于不可变性**:字段注入的依赖在实例化后可以被更改。 - **依赖关系不清晰**:依赖被隐藏在字段中,不如构造函数注入直观。 Spring 更推荐使用构造函数注入,因为它能带来更清晰的依赖关系、更好的不可变性和测试支持。发布于 2024-11-04 12:25 •IP属地 辽宁举报评论收藏
公众号进入网站体验更佳

