假设我们在类中的各个字段上使用
@Autowired
注解,并且我们没有编写也可以设置字段的 setter 或构造函数。
问题 - 访问修饰符应该是什么,
private
或 package-private
(即无)?
例如:
public class MyClass {
@Autowired
private MyService myService;
}
对
public class MyClass {
@Autowired
MyService myService;
}
在第一种情况下(
private
字段)Spring使用反射来连接字段,即使它没有setter。
第二种情况(
package-private
字段)允许我们在需要出于测试目的扩展类时访问这些字段(例如,设置模拟)。
所以这两种情况都工作得很好,但是更推荐哪一种,特别是在测试方面?
所以这两种情况都工作得很好,但是更推荐哪一种,特别是在测试方面?
我认为属性应该是
private
:
@Autowired
private MyService myService;
因为使用 getter 方法来提供对属性的访问而不是允许其他类直接访问它们总是好的。
出于测试目的,注入
mocks
的 private properties
的工作方式与 package-private
属性的工作方式相同。
例如,使用
Mockito
,您可以将 private MyService
的模拟注入到 MyClass
中,如下所示:
public class MyClassTest {
@Mock
MyService service;
@InjectMocks
MyClass serv = new MyClass();
@Before
public void init() {
MockitoAnnotations.initMocks(this);
}
}
我通常更喜欢将字段设为私有并使用 setter 注入:
public class MyClass {
private MyService myService;
@Autowired
public void setMyService(MyService myService) {
this.myService = myService;
}
}
允许服务@Autowired,但设置一个模拟实例以进行单元测试。
第一种情况还允许您根据框架注入模拟。例如使用 Mockito 的
@InjectMocks
注释。您在 Spring 测试中也有 ReflectionTestUtils.setField
,...
我个人不太喜欢出于测试目的而过多修改类,所以我会选择第一种情况。但归根结底,这主要取决于您首选的测试框架。
我通常不会将
@Autowired
用于 private
字段或方法。 @Autowired
表示外部人员将设置此字段。另一方面,“私有”意味着除了这个类之外任何人都不允许使用它。
如果 JIT 编译器以某种方式优化代码,混合
@Autowired
和 private
理论上可能会导致问题。它可能是与 Java 内存模型并发性相关的问题,即“仅限生产”和“不可能重现”。
我会让自动连线字段至少在包中可见。作为免费的奖励,它将允许编写单元测试而无需技巧和解决方法。
更新:此外,我会将此类字段声明为
volatile
以避免与 Java 内存模型相关的可见性冲突。 Spring 开发人员使用了一些技巧来使自动装配字段工作,而无需显式同步访问,但我不确定这些技巧是否可以在任何硬件上的任何 JVM 中顺利运行。
我宁愿在 @Autowired 字段上使用 private,原因如下:我使用这些字段进行依赖注入,一般在服务类中,以使用其他服务类。在这种情况下,我想将这些字段保留在当前类中。