使用Spring进行依赖注入时,很多大佬都推荐使用构造方法注入,而非使用在属性上添加
@Autowired
注入,而且还说这是Spring官方说的,真的是这样吗?
使用Spring进行依赖主要的方式有很多,主流的使用方式有两种:
-
1.在属性或者
setter
方法上使用@Autowired
进行注入 -
2.在构造方法上使用
@Autowired
进行注入
那么哪种方式更好一点呢?
很巧,在看Spring
文档的时候看到了这样一段描述:
可以参考:Dependency Injection
上面描述主要表达三个信息:
-
1.两者可以混合使用,对于必须的依赖项,使用构造函数;而对于可选的依赖项,使用
setter
方法或属性依赖。 -
2.如果依赖项是不可变的,建议使用构造器进行注入,但是构造器参数过多时,意味着类可能承担了过多的职责,代码就变的不好维护。
-
3.对于一些三方框架,构造方法或者
setter
方法没有对外暴露,依赖注入的方式需要根据实际情况进行选择。
如果把以上三点总结成一点的话,就是:根据具体场景进行选择。
既然是这样,那么为啥还有大佬一直强调:要使用构造器注入呢?难道大佬没有看文档吗?
我觉得应该是看过了上面的文档,然后才这样强调的,原因在于:
-
1.为了方便管理和统一编码风格,有些公司会有自己特定的开发模式和规范。
-
2.同时更加看重构造器注入的带来的好处。
那么使用构造器注入有哪些优点呢?
1.不变性
通过将依赖项设置为 final,我们确保了在对象创建之后,依赖项不能被修改。这提高了代码的可维护性和可预测性。
@Component
public class MyBean {
private final Dependency1 dependency1;
// 只有一个构造函数时,可以省略@Autowired
public MyBean(Dependency1 dependency1) {
this.dependency1 = dependency1;
}
}
2.更清晰的依赖
构造方法注入明确地指定了类所需的依赖项,因此理解代码需要哪些输入变得非常容易。
public class MyBean {
private final Dependency1 dependency1;
private final Dependency2 dependency2;
public MyBean(Dependency1 dependency1, Dependency2 dependency2) {
this.dependency1 = dependency1;
this.dependency2 = dependency2;
}
}
3.可测试性
构造方法注入简化了测试过程,因为我们可以在创建类的实例时很容易地使用 mock 对象替代真实依赖。
public class MyBeanTest {
@Test
public void testMyBean() {
Dependency1 mockDependency1 = Mockito.mock(Dependency1.class);
Dependency2 mockDependency2 = Mockito.mock(Dependency2.class);
MyBean myBean = new MyBean(mockDependency1, mockDependency2);
// ...编写测试用例...
}
}
4.更容易发现错误
构造方法注入确保必需的依赖在对象创建时就满足,这有助于发现问题并在应用启动期间捕获错误。
public class MyBean {
private final Dependency1 dependency1;
public MyBean(Dependency1 dependency1) {
if(dependency1 == null) {
throw new IllegalArgumentException("Dependency1 cannot be null");
}
this.dependency1 = dependency1;
}
}
在使用构造器注入的过程中,如果依赖项不断变化,那么每次变化,构造器方法签名就需要不断修改,比较麻烦,这里推荐大家使用一个插件:Lombok
。
如果你的项目使用了 Lombok 的话,可以使用 @AllArgsConstructor
注解自动生成包含所有成员变量的构造方法。
这样,在添加新的属性时,就不再需要显式地修改构造方法。
import lombok.AllArgsConstructor;
@AllArgsConstructor
public class MyBean {
private final Dependency1 dependency1;
private final Dependency2 dependency2;
}
对 Lombok 不熟悉的老铁可以参考:lombok使用与原理介绍
今日分享如果对你有帮助,帮忙点个关注