当前位置: 首页 > 后端技术 > Java

看看Spring的三种注入方式,哪种注入方式最好?

时间:2023-04-02 01:57:53 Java

@[toc]循环依赖是我们日常编程中应该避免的问题。其实这个问题也是可以避免的。但是,由于一般的原因,我们还是会遇到一些循环依赖的问题,尤其是在面试的过程中。面试考察循环依赖,主要考察考生对Spring源码的熟悉程度,因为需要把问题解释清楚,而且涉及到大量的Spring源码。宋兄今天抽空跟大家简单聊了聊这个话题。问题相当大。我可能会花几篇文章分享给大家。今天先说说实例的注入方式。1.如何注入实例首先,我们来看一下Spring中是如何注入实例的。总结起来无外乎三种:属性注入、set方法注入、构造函数注入。让我们分别看看它们。1.1属性注入属性注入是最常见也是使用最多的注入方式。代码如下:@ServicepublicclassBService{@AutowiredAServiceaService;//...}这里是使用@Autowired注解的注入。另外还有@Resource、@Inject等注解,可以实现注入。但是不知道小伙伴们有没有注意到,在IDEA中,如果使用属性注入,会有一个警告??:不推荐使用属性注入!原因我们稍后再说。1.2Set方法注入set方法注入过于臃肿,实际很少使用:@ServicepublicclassBService{AServiceaService;@AutowiredpublicvoidsetaService(AServiceaService){this.aService=aService;}}这段代码一看就不舒服,坚决不。1.3构造函数注入构造函数注入方法如下:@ServicepublicclassAService{BServicebService;@AutowiredpublicAService(BServicebService){this.bService=bService;}}如果类只有一个构造函数,@Autowired注解可以省略;如果类中有多个构造函数,则需要添加@Autowired明确指定使用哪个构造函数。2、实例注入方式大PK上面列举了三种注入方式,那么三种注入方式有什么区别呢?下面结合Spring的官方文档来分析一下。宋哥翻出12年前的Spring3.0文档(https://docs.spring.io/spring...),里面有这么一段话:我简单翻译一下(意译):UsetheconstructortoinjectOr使用set方法注入?由于构造函数注入和set方法注入可以混合使用,如果需要强制注入,我们可以使用构造函数注入;如果是可选注入,我们可以使用set方法注入。当然,我们在setter上使用@Required注解,强制set方法注入。Spring团队通常提倡setter注入,因为当属性过多时,构造器会显得特别臃肿,尤其是当属性是optional的时候(propertyoptional意味着不需要通过构造器注入)。setter方法注入的另一个好处是它使类的属性能够在以后重新配置或重新注入。一些纯粹主义者喜欢基于构造函数的注入,这意味着所有属性都被初始化,缺点是对象变得不太适合重新配置和重新注入。另外,在一些特殊的场景下,比如一个第三方类要注入到Spring容器中,但是这个类没有提供set方法,那么这时候就只能使用构造函数注入了。英文水平有限,大概翻译一下。小伙伴们,重点看加粗的部分,也就是说在Spring3.0时代,官方还是提倡set方法注入。但是从Spring4.x开始,官方不再推荐这种注入方式,转而推荐使用构造函数注入。看看Spring4.x的文档是怎么说的(https://docs.spring.io/spring...):这部分内容我就不一一翻译了,大家重点看第一句第二段:Springteamgeneraladvocatesconstructorinjection这句话的意思是Spring团队提倡通过构造方法进行注入。才大版本更新,Spring怎么变的?别担心,人们也给出了使用构造函数注入的理由。第二段的翻译大概是这样的:通过构造函数注入,可以保证注入的组件是不可变的,可以保证需要的依赖不为空。此外,当返回到客户端(组件)代码时,构造函数注入的依赖项始终保证处于完全初始化状态。上面这段话主要讲了三件事:Dependencyisimmutable:这个很容易理解。依赖是通过构造方法注入的,必须在创建对象的时候注入依赖。一旦对象创建成功,注入的依赖只能在以后使用。修改了,这个依赖于不变性(通过set方法注入,以后也可以通过set方法修改)。依赖不为空:通过构造函数注入时,会自动检查注入的对象是否为空。如果为空,则注入失败;如果不为空,则注入成功。全初始化:由于获得了依赖对象(初始化了这个依赖对象),并调用了待初始化组件的构造函数,最终得到了全初始化对象。在Spring3.0的文档中,官方说如果使用构造函数注入,过多的属性可能会使代码非常臃肿,所以在4.0的文档中,官方也对这种说法做了一些修正:如果使用构造函数注入,参数太多导致代码过于臃肿,那么就需要考虑这个类的设计是否合理,这个类是不是混杂了太多其他不相关的功能,这个类是否做到了职责单一。嗯,你说的总是对的!这是构造函数注入和set方法注入的问题。所以我们上面提到不推荐使用属性注入。这是怎么回事?属性注入其实有一个明显的缺点,就是对于IOC容器以外的环境,实现类除了使用反射提供它需要的依赖外,不能被复用。因为这个类没有提供属性的set方法或者相应的构造方法来完成属性的初始化。也就是说,如果你使用属性注入,你的类只能在IOC容器中使用。如果你想自己new这个类的对象,那么相关的依赖是无法注入的。以上分析基于Spring官方文档。日常开发中应该多一些属性注入。我们不必为此担心。代码怎么写就是怎么写。Spring官方的态度可以理解。当然,如果项目允许的话,不妨试试Spring推荐的编码约定。3.总结好了,今天就和小伙伴们聊一聊Spring中的注入方式,因为最近又要接Spring源码分析,先来个简单的热身吧哈哈~