Spring @Autowire 注解用于属性或构造函数的区别
- 背景
- 回复1
- 回复2
- 回复3
背景
因此,由于我一直在使用 Spring
,所以如果我要编写具有依赖项的 Service
,我将这样实现:
方法 A
@Component
public class SomeService {
@Autowired
private SomeOtherService someOtherService;
}
但是我现在发现了使用另一种约定也可以实现相同目标的代码:
方法 B
@Component
public class SomeService {
private final SomeOtherService someOtherService;
@Autowired
public SomeService(SomeOtherService someOtherService){
this.someOtherService = someOtherService;
}
}
这两种方法都可以达到相同的目的。但是使用第二种方式有一些优势吗?对我来说,它在类和单元测试中创建了更多代码。 (必须编写构造函数,而不能使用 @InjectMocks
)
有什么我不清楚的吗? 除了将代码添加到单元测试中之外,Autowired
构造函数还有其他功能吗? 方法 B 是进行依赖注入更优的吗?
回复1
是的,实际上建议使用方法 B(称为构造函数注入),而不是使用属性注入,它具有以下优点:
- 依存关系明确。在测试或在任何其他情况下实例化对象时(例如在 config 类中显式创建 bean 实例),都不会忽略此构造方法;
- 依赖关系可以是 final,这有助于增强鲁棒性和线程安全性;
- 您不需要反射来设置依赖项。
InjectMocks
仍然可用,但不是必需的。 您可以自己创建mocks
并通过调用构造函数将其注入。
回复2
我将用简单的话向您解释:
- 在
方法 A
中,您允许任何类(在Spring容器外部/内部的不同类中)使用默认构造函数(例如new SomeService()
)创建实例,这是不规范的。因为您需要SomeOtherService
对象(作为依赖项) 为您的SomeService
。 -
方法 B
是首选方法,因为它不允许在没有实际解决SomeOtherService
依赖关系的情况下创建SomeService
对象。
回复3
请注意,从Spring 4.3开始,您甚至不需要在构造函数上使用 @Autowired
,因此您可以使用 Java 样式编写代码,而不必使用 Spring 的注释。您的代码段如下所示:
@Component
public class SomeService {
private final SomeOtherService someOtherService;
public SomeService(SomeOtherService someOtherService){
this.someOtherService = someOtherService;
}
}