【Spring】关于Spring的三种注入方式的分析

随着时代的发展,Spring项目的依赖注入方式越来越倾向于使用注解的方式。当然在一些比较老的项目,依然存在xml配置的方式,这里不讨论这些情况。常用的依赖注入的注解无非就是@Resource和@Autowired

在 Spring 中实现依赖注入的最常见方式有以下 3 种:

  • 属性注入(Field Injection)
  • Setter 注入(Setter Injection)
  • 构造方法注入(Constructor Injection)

每种方式都有其优缺点,下面我们就简单的来分析一下。

1、属性注入

日常开发中,属性注入是我们最常用的一种注入方式,代码实现如下:
在这里插入图片描述
优点:主要是使用简单,只需在属性注解即可实现依赖注入。
缺点:无法注入不可变对象、只适用于IoC容器以及可能违背单一设计原则。

注意:属性注入在底层实现是通过反射技术直接访问被注解的属性(Filed)注入进去的,并不会调用对应的set方法。

2、Setter注入

Setter注入,故名思意就是Spring在依赖注入的时候调用被注解的set方法,代码实现如下:
在这里插入图片描述
优点:通用性较高,可以在不重启容器的情况下修改配置;
缺点:不能注入不可变对象,且注入的对象可被修改。

注意:父类的属性注入和Setter注入,在创建子类的Bean时也会依赖注入。

3、构造方法注入

构造方法注入,故名思意就是Spring在依赖注入的时候调用被注解的构造方法,代码实现如下:
在这里插入图片描述
下面讨论一下构造方法注入时可能出现的几种情况:

1、当Bean中只有一个构造方法时,可以省略对应的注解,注入时会自动调用这一个构造方法:
在这里插入图片描述
2、如果Bean中有多个重载的构造方法时,需要使用注解到对应的构造方法上,则注入时就会选择这个构造方法:
在这里插入图片描述
3、但是Bean中有多个重载的构造方法时,并且没有使用注解标注到构造方法上,那么注入时会使用默认构造方法
在这里插入图片描述
4、Bean中有多个重载的构造方法时,没有提供默认构造方法,也没有使用注解标注到构造方法上,则注入的时候会报错:
在这里插入图片描述在这里插入图片描述
优点:完全符合单一职责设计原则,提前确保依赖不为空,并且可以注入不可变对象;
缺点:如果依赖过多会使构造方法显得臃肿(这个其实也不算是缺点吧,可以使用Lombok注解解决)。
综上,我们可以知道构造方法注入比其他两种更加适合依赖注入,同时也是官方推荐的方法,建议平时使用这种注入方式。

4、注入方式的先后顺序

如果一个Bean中同时出现这三种注入方式的时候,那么它们注入的先后顺序是怎样的呢?当然,我们可以首先知道构造方法注入必然是第一个注入的,因为在创建Bean对象完成后就马上调用构造方法来初始化对象状态信息,这一步其实就是构造方法注入。所以这里讨论的是属性注入和Setter注入的先后顺序,我们直接看一个测试例子就明白了:
在这里插入图片描述
运行结果:
在这里插入图片描述
综上,可以知道当三种注入方式同时存在时,注入顺序为构造方法注入 —> 属性注入 —> Setter注入,在实际开发中建议只使用一种注入方式。

为什么属性注入会比Setter注入先执行呢?可以看【Spring】关于Spring中Bean的生命周期填充Bean(依赖注入)说明。

5、Lombok注解与构造方法注入

前面说到构造方法注入的缺点就是过于臃肿的问题,我们可以使用Lombok的两个注解来解决这个问题,分别是@AllArgsConstructor和@RequiredArgsConstructor

5.1 @AllArgsConstructor

自动生成一个包含所有实例成员属性的构造函数。代码如下:
在这里插入图片描述
反编译代码如下:
在这里插入图片描述
可以看到不管属性是什么修饰符的,只要是实例成员属性都会添加到构造方法中。

5.2 @AllArgsConstructor

为类中所有的final修饰或者@NonNull的实例成员属性生成一个构造方法。代码如下:
在这里插入图片描述
反编译代码如下:
在这里插入图片描述

注意:这两个注解都是只包含非staic的成员属性。

5.3 不要与@Value连用

这两个注解都不应该与@Value注解连用。因为@Value注解通常只用于基本数据类型或者String类型的属性上,那么生成的构造方法也会带上这些属性。如果我们生成的构造方法用于注入时,那么就会出现错误,因为很少情况会将基本数据类型和String类型交于IOC管理,如下所示:
在这里插入图片描述
在这里插入图片描述
其二,如果是@RequiredArgsConstructor注解,那么对应的属性应该是final修饰或者@NonNull修饰的,而 @Value注解是不能用在static属性和final属性上的。

所以,@AllArgsConstructor和@RequiredArgsConstructor都不要与@Value一起使用。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值