Spring @Полученные поля - какие модификаторы доступа, частные или пакетно-частные?
Скажем, что мы используем аннотацию @Autowired
по различным полям в классе и что мы не записываем сеттеры или конструкторы, которые также могут устанавливать поля.
Вопрос: какой должен быть модификатор доступа, private
или package-private
(т.е. нет)?
Например:
public class MyClass {
@Autowired
private MyService myService;
}
против
public class MyClass {
@Autowired
MyService myService;
}
В первом случае (private
поля) Spring использует отражение для подключения поля, даже если у него нет setter.
Второй случай (package-private
) позволяет нам иметь доступ к этим полям (например, для настройки mocks), если нам нужно расширить класс для целей тестирования.
Таким образом, оба случая работают нормально, но что более рекомендуется, особенно в отношении тестирования?
Ответы
Ответ 1
Первый случай также позволяет вам вводить mocks в зависимости от структуры. Например, используя аннотацию @InjectMocks
Mockito. У вас также есть ReflectionTestUtils.setField
в тесте Spring,...
Я лично не слишком люблю слишком много менять классы для тестирования, поэтому я бы пошел на первый случай. Но в конце дня это в основном зависит от вашей предпочтительной структуры тестирования.
Ответ 2
Таким образом, оба случая работают нормально, но что более рекомендуется, особенно в отношении тестирования?
Я думаю, что свойства должны быть private
:
@Autowired
private MyService myService;
Как всегда полезно иметь методы getter для предоставления доступа к свойствам вместо того, чтобы другие классы имели прямой доступ к ним.
И для целей тестирования вставка mocks
of 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
Я обычно предпочитаю, чтобы поле было приватным и использовало инъекцию установщика:
public class MyClass {
private MyService myService;
@Autowired
public void setMyService(MyService myService) {
this.myService = myService;
}
}
позволяя услуге быть @Autowired, но настроен с помощью изделенного экземпляра для модульного тестирования.