假设我们在类的各个字段中使用@Autowired
注释,并且我们没有编写也可以设置字段的setter或构造函数。
问题 - 访问修饰符应该是什么,private
或package-private
(即无)?
例如:
public class MyClass {
@Autowired
private MyService myService;
}
VS
public class MyClass {
@Autowired
MyService myService;
}
在第一种情况下(private
字段),Spring使用反射来连接字段,即使它没有setter。
第二种情况(package-private
字段)允许我们能够访问这些字段(例如,设置模拟),如果我们需要扩展类以进行测试。
因此两种情况都很好,但更推荐哪种情况,特别是在测试方面?
答案 0 :(得分:6)
第一种情况也允许你根据框架注入模拟。例如,使用Mockito的@InjectMocks
注释。你在Spring测试中也有ReflectionTestUtils.setField
,...
我个人并不太喜欢为测试目的过多地修改类,所以我会选择第一种情况。但最终这取决于您首选的测试框架。
答案 1 :(得分:6)
我通常更喜欢将字段设为私有并使用setter注入:
public class MyClass {
private MyService myService;
@Autowired
public void setMyService(MyService myService) {
this.myService = myService;
}
}
允许服务为@Autowired,但使用模拟实例进行单元测试。
答案 2 :(得分:6)
因此两种情况都很好,但更推荐哪种情况,特别是在测试方面?
我认为属性应为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);
}
}
答案 3 :(得分:2)
我通常不会将@Autowired用于私有字段或方法。 @Autowired意味着,来自外部的人将设置此字段。 "私人"另一方面,除了这门课以外,没有人可以使用它。
如果JIT编译器以某种方式优化了这段代码,那么混合@Autowired和private理论上会导致问题。它可能是一个与Java内存模型并发相关的问题,它只能用于生产,不可能再现。
我会使Autowired字段至少包可见。作为免费奖金,它可以在没有技巧和变通方法的情况下编写单元测试。
答案 4 :(得分:0)
由于某些原因,我宁愿在@Autowired字段上使用private: