Spring @Autowired 字段 - 哪个访问修饰符是私有的还是包私有的?

问题描述 投票:0回答:5

假设我们在类中的各个字段上使用

@Autowired
注解,并且我们没有编写也可以设置字段的 setter 或构造函数。

问题 - 访问修饰符应该是什么,

private
package-private
(即无)?

例如:

public class MyClass {
    @Autowired
    private MyService myService;
}

public class MyClass {
    @Autowired
    MyService myService;
}

在第一种情况下(

private
字段)Spring使用反射来连接字段,即使它没有setter。

第二种情况(

package-private
字段)允许我们在需要出于测试目的扩展类时访问这些字段(例如,设置模拟)。

所以这两种情况都工作得很好,但是更推荐哪一种,特别是在测试方面?

java spring unit-testing private access-modifiers
5个回答
12
投票

所以这两种情况都工作得很好,但是更推荐哪一种,特别是在测试方面?

我认为属性应该是

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);
    }
}

9
投票

我通常更喜欢将字段设为私有并使用 setter 注入:

public class MyClass {

    private MyService myService;

    @Autowired
    public void setMyService(MyService myService) {
        this.myService = myService;
    }
}   

允许服务@Autowired,但设置一个模拟实例以进行单元测试。


8
投票

第一种情况还允许您根据框架注入模拟。例如使用 Mockito 的

@InjectMocks
注释。您在 Spring 测试中也有
ReflectionTestUtils.setField
,...

我个人不太喜欢出于测试目的而过多修改类,所以我会选择第一种情况。但归根结底,这主要取决于您首选的测试框架。


5
投票

我通常不会将

@Autowired
用于
private
字段或方法。
@Autowired
表示外部人员将设置此字段。另一方面,“私有”意味着除了这个类之外任何人都不允许使用它。

如果 JIT 编译器以某种方式优化代码,

混合

@Autowired
private
理论上可能会导致问题。它可能是与 Java 内存模型并发性相关的问题,即“仅限生产”和“不可能重现”。 我会让自动连线字段至少在包中可见。作为免费的奖励,它将允许编写单元测试而无需技巧和解决方法。

更新:

此外,我会将此类字段声明为

volatile

以避免与 Java 内存模型相关的可见性冲突。 Spring 开发人员使用了一些技巧来使自动装配字段工作,而无需显式同步访问,但我不确定这些技巧是否可以在任何硬件上的任何 JVM 中顺利运行。

我宁愿在 @Autowired 字段上使用 private,原因如下:

2
投票

我使用这些字段进行依赖注入,一般在服务类中,以使用其他服务类。在这种情况下,我想将这些字段保留在当前类中。

此外,扩展此类可能会导致不同的逻辑,因此可能需要 @Autowired 字段的另一种实现,因此使用私有而不是包私有。
  • 此外,在重构时,它有助于查看何时不再使用此类字段,因为包私有字段在未使用时不会显示警告(假设您的 IDE 是 Eclipse - 我实际上不知道其他 IDE)。
© www.soinside.com 2019 - 2024. All rights reserved.