【Spring】为什么不建议使用@Autowired
- 开篇词:
- 干货篇:
- 1.知识回顾
- 2.@Autowired和其他注入方式的对比
- 1.@Autowired 注入(字段注入)
- 2.构造器注入
- 3.Setter 方法注入
- 3.为什么spring官方不推荐使用
- 1. 违反封装原则
- 2. 依赖关系不明确
- 3. 难以进行单元测试
- 4. 可能导致空指针异常
- 5. 依赖注入的歧义性
- 总结篇:
- 我是杰叔叔,一名沪漂的码农,下期再会!
开篇词:
最近提交PR后,有同事添加了comments:建议@autowired替换为构造器注入,正好借此来聊一下这个司空见惯的注解
干货篇:
1.知识回顾
@Autowired 是 Spring 框架中的一个注解,用于实现依赖注入(Dependency Injection, DI)。在 Spring 应用程序中,
@Autowired 可以自动地将一个 bean 注入到另一个 bean 中,前提是 Spring 容器中存在该类型的 bean。这使得 Spring 应用程序的组件之间的耦合度降低,提高了代码的可测试性和可维护性。
2.@Autowired和其他注入方式的对比
1.@Autowired 注入(字段注入)
优点:
- 简单易用:只需在字段上添加 @Autowired 注解,Spring 容器会自动注入匹配的 bean,减少了代码量。
- 灵活性高:可以在类的任何字段上使用,不受限制。
缺点:
- 依赖关系不明确:其他开发者难以一眼看出类的依赖关系,增加了理解和维护的难度。
- 难以测试:由于依赖是自动注入的,测试时难以替换或模拟依赖对象。
2.构造器注入
优点:
- 明确依赖关系:通过构造器参数明确指定了类的依赖关系,提高了代码的可读性和可维护性。
- 支持不可变对象:可以注入 final 修饰的字段,确保对象在创建后不会被修改。
- 避免循环依赖:Spring 容器能够自动检测并处理构造器注入中的循环依赖问题。
- 有利于单元测试:可以通过构造器注入模拟或替换依赖对象,便于编写单元测试。
缺点:
- 灵活性较低:对类的依赖关系有严格的顺序要求,可能导致代码不够灵活。
- 启动时间稍长:由于需要处理依赖关系的顺序和循环依赖问题,可能会稍微增加应用的启动时间。
3.Setter 方法注入
优点:
- 灵活性高:可以在对象创建后通过 Setter 方法注入依赖,支持依赖的延迟加载。
- 支持可选依赖:如果依赖不是必需的,可以在 Setter 方法中处理 null 值,避免空指针异常。
- 有利于单元测试:与构造器注入类似,可以通过 Setter 方法注入模拟或替换依赖对象。
缺点:
- 依赖关系不够明确:虽然比字段注入稍好一些,但依赖关系仍然不够直观。
- 可能违反单一职责原则:如果 Setter 方法过多,可能会使类的职责不够单一。
3.为什么spring官方不推荐使用
1. 违反封装原则
直接在类的成员变量上使用@Autowired会导致类的内部状态对外部可见,这违反了面向对象编程中的封装原则。封装是面向对象编程的核心概念之一,它要求将对象的内部状态隐藏起来,只对外提供有限的接口进行交互。字段注入破坏了这种封装性,使得类的内部状态变得不可控,增加了潜在的风险。
2. 依赖关系不明确
字段注入将依赖关系隐藏在类的内部,使得类的依赖关系不明显。这会导致代码的可读性和可维护性下降。其他开发者在阅读代码时,很难一眼看出该类依赖于哪些其他类,从而增加了理解和修改代码的难度。
3. 难以进行单元测试
由于依赖的实例是自动注入的,测试时很难对依赖进行模拟或替换。这会增加单元测试的复杂性,并且可能导致测试覆盖率不足。相比之下,构造器注入或Setter方法注入使得依赖关系更加明确,便于在测试时通过构造器或Setter方法注入模拟对象。
4. 可能导致空指针异常
在字段注入的情况下,如果Spring容器中没有找到匹配的bean,那么注入的字段将保持为null。这可能导致在后续的代码执行中出现空指针异常(NPE),而这种异常在编译时是无法检测到的,只能在运行时才能发现。
5. 依赖注入的歧义性
如果Spring容器中存在多个相同类型的bean,并且你尝试使用@Autowired进行注入,那么Spring将无法确定应该注入哪一个bean,从而导致异常。虽然可以通过@Qualifier注解来指定要注入的bean的名称,但这增加了代码的复杂性和出错的可能性。
总结篇:
Spring官方不推荐使用@Autowired进行字段注入的主要原因是它违反了封装原则、导致依赖关系不明确、难以进行单元测试、可能导致空指针异常以及存在依赖注入的歧义性。为了编写更加健壮、易于理解和维护的代码,建议采用构造器注入或Setter方法注入作为依赖注入的替代方案。