围观:
前言
本章的内容主要是想探讨我们在进行Spring 开发过程当中,关于依赖注入的几个知识点。感兴趣的读者可以先看下以下问题:
-
@Autowired
,@Resource
,@Inject
三个注解的区别 -
当你在使用 @Autowired
时,是否有出现过Field injection is not recommended
的警告?你知道这是为什么吗? -
Spring 依赖注入有哪几种方式?官方是怎么建议使用的呢?
如果你对上述问题都了解,那我个人觉得你的开发经验应该是不错的👍。
下面我们就依次对上述问题进行解答,并且总结知识点。
@Autowired
, @Resource
, @Inject
三个注解的区别
Spring 支持使用@Autowired
, @Resource
, @Inject
三个注解进行依赖注入。下面来介绍一下这三个注解有什么区别。
@Autowired
@Autowired
为Spring 框架提供的注解,需要导入包org.springframework.beans.factory.annotation.Autowired
。
这里先给出一个示例代码,方便讲解说明:
private final Svc svc;
@Autowired
public HelpService(@Qualifier("svcB") Svc svc) {
this.svc = svc;
}
在
Spring 4.3
及以后的版本中,如果这个类只有一个构造方法,那么这个构造方法上面也可以不写@Autowired
注解。
基于 field 注入的好处
正如你所见,这种方式非常的简洁,代码看起来很简单,通俗易懂。你的类可以专注于业务而不被依赖注入所污染。你只需要把@Autowired
扔到变量之上就好了,不需要特殊的构造器或者set方法,依赖注入容器会提供你所需的依赖。
基于 field 注入的坏处
成也萧何败也萧何
基于 field 注入虽然简单,但是却会引发很多的问题。这些问题在我平常开发阅读项目代码的时候就经常遇见。
-
容易违背了单一职责原则 使用这种基于 field 注入的方式,添加依赖是很简单的,就算你的类中有十几个依赖你可能都觉得没有什么问题,普通的开发者很可能会无意识地给一个类添加很多的依赖。但是当使用构造器方式注入,到了某个特定的点,构造器中的参数变得太多以至于很明显地发现something is wrong。拥有太多的依赖通常意味着你的类要承担更多的责任,明显违背了单一职责原则(SRP:Single responsibility principle)。
这个问题在我司的项目代码真的很常见。
-
依赖注入与容器本身耦合
依赖注入框架的核心思想之一就是受容器管理的类不应该去依赖容器所使用的依赖。换句话说,这个类应该是一个简单的POJO(Plain Ordinary Java Object)能够被单独实例化并且你也能为它提供它所需的依赖。
这个问题具体可以表现在:
-
你的类和依赖容器强耦合,不能在容器外使用
-
你的类不能绕过反射(例如单元测试的时候)进行实例化,必须通过依赖容器才能实例化,这更像是集成测试
-
不能使用属性注入的方式构建不可变对象(
final
修饰的变量)
Spring 开发团队的建议
Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies.
简单来说,就是
-
强制依赖就用构造器方式
-
可选、可变的依赖就用setter 注入
当然你可以在同一个类中使用这两种方法。构造器注入更适合强制性的注入旨在不变性,Setter注入更适合可变性的注入。
让我们看看Spring 这样推荐的理由,首先是基于构造方法注入,
The Spring team generally advocates constructor injection as it enables one to implement application components as immutable objects and to ensure that required dependencies are not null. Furthermore constructor-injected components are always returned to client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns.
Spring 团队提倡使用基于构造方法的注入,因为这样一方面可以将依赖注入到一个不可变的变量中 (注:final
修饰的变量),另一方面也可以保证这些变量的值不会是 null。此外,经过构造方法完成依赖注入的组件 (注:比如各个 service
),在被调用时可以保证它们都完全准备好了。与此同时,从代码质量的角度来看,一个巨大的构造方法通常代表着出现了代码异味,这个类可能承担了过多的责任。
而对于基于 setter 的注入,他们是这么说的:
Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later.
基于 setter 的注入,则只应该被用于注入非必需的依赖,同时在类中应该对这个依赖提供一个合理的默认值。如果使用 setter 注入必需的依赖,那么将会有过多的 null 检查充斥在代码中。使用 setter 注入的一个优点是,这个依赖可以很方便的被改变或者重新注入。
小结
以上就是本文的所有内容,希望阅读本文之后能让你对Spring 的依赖注入有更深的理解。
如果本文有帮助到你,希望能点个赞,这是对我的最大动力🤝🤝🤗🤗。
参考
-
Setter-based dependency injection[1]
-
Field Dependency Injection Considered Harmful[2]
-
IDEA 警告 Field injection is not recommended[3]
参考资料
https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/beans.html#beans-setter-injection: https://link.juejin.cn?target=https%3A%2F%2Fdocs.spring.io%2Fspring%2Fdocs%2F4.2.x%2Fspring-framework-reference%2Fhtml%2Fbeans.html%23beans-setter-injection
[2]
https://www.vojtechruzicka.com/field-dependency-injection-considered-harmful/: https://link.juejin.cn?target=https%3A%2F%2Fwww.vojtechruzicka.com%2Ffield-dependency-injection-considered-harmful%2F
[3]
https://boris1993.github.io/projects/java/coding-tips/idea-warninig-field-injection-is-not-recommended.html: https://link.juejin.cn?target=https%3A%2F%2Fboris1993.github.io%2Fprojects%2Fjava%2Fcoding-tips%2Fidea-warninig-field-injection-is-not-recommended.html
感谢阅读,希望对你有所帮助 :)
来源:juejin.cn/post/6844904056230690824

与其在网上拼命找题? 不如马上关注我们~
PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。点“在看”支持我们吧!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/8764.html