Правильный подход — использовать внедрение конструктора, когда это возможно. Благодаря этому ясно, каковы зависимости объекта, и вы не сможете создать их, если не предоставите все, что требуется.
Используйте внедрение конструктора, как показано ниже.
public class ProjectService {
private final ProjectRepository projectRepository;
private final TaskRepository taskRepository;
public ProjectService(TaskRepository taskService, ProjectRepository projectService) {
Assert.notNull(taskService);
Assert.notNull(projectService);
this.taskRepository = taskService;
this.projectRepository = projectService;
}
public Project load(Long projectId) {
return projectRepository.findById(projectId);
}
}
final
поля гарантируют, что зависимости не изменятся после инициализации объекта
Assert.notNull
гарантирует, что вы не поместите нулевые значения вместо реальных объектов.
Когда вы используете инъекцию сеттера или инъекцию поля, ваш API позволяет создавать объект в неправильном состоянии. Рассмотрим пример:
public class ProjectService {
private ProjectRepository projectRepository;
private TaskRepository taskRepository;
public Project load(Long projectId) {
return projectRepository.findById(projectId);
}
@Autowired
public void setProjectRepository(ProjectRepository projectRepository) {
this.projectRepository = projectRepository;
}
@Autowired
public void setTaskRepository(TaskRepository taskRepository) {
this.taskRepository = taskRepository;
}
}
ProjectService projectService = new ProjectService();
projectService.load(1L); // NullPointerException is thrown
Для всех необязательных зависимостей вы можете использовать инъекцию сеттера. Подробнее читайте в блоге Оливера Гирке (руководитель Spring Data): http://olivergierke.de/2013/11/why-field-injection-is-evil/
Обновление от 15 января 2019 г.
Начиная с Spring 4.3 нет необходимости помещать аннотацию @Autowired
в конструктор, если присутствует только один конструктор.
person
Maciej Walkowiak
schedule
25.11.2014