Spring @Autowired字段 - 访问修饰符,私有或包私有?

时间:2013-10-30 12:30:00

标签: java spring unit-testing private access-modifiers

假设我们在类的各个字段中使用@Autowired注释,并且我们没有编写也可以设置字段的setter或构造函数。

问题 - 访问修饰符应该是什么,privatepackage-private(即无)?

例如:

public class MyClass {
    @Autowired
    private MyService myService;
}

VS

public class MyClass {
    @Autowired
    MyService myService;
}

在第一种情况下(private字段),Spring使用反射来连接字段,即使它没有setter。

第二种情况(package-private字段)允许我们能够访问这些字段(例如,设置模拟),如果我们需要扩展类以进行测试。

因此两种情况都很好,但更推荐哪种情况,特别是在测试方面?

5 个答案:

答案 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:

  • 我通常在服务类中使用这些字段进行依赖项注入,以使用其他服务类。在那种情况下,我想将这些字段保留在当前类中。
  • 此外,扩展此类可能导致不同的逻辑,因此可能需要@Autowired字段的另一种实现,因此使用private而不是package-private。
  • 此外,在重构时,它有助于查看何时不再使用该字段,因为未使用时,package-private字段不会显示警告(假设您的IDE是Eclipse-我实际上不知道其他IDE )。