【发布时间】:2015-01-23 18:56:23
【问题描述】:
什么时候在Spring中使用构造函数注入?
我听说在使用组件之前绝对必须拥有依赖类的实例时,构造函数注入特别有用。但这是什么意思?
谁能在以下时刻用一些简单的例子来解释我:
- 使用构造函数注入有什么好处?
- 什么是动态构造函数注入?
【问题讨论】:
-
注入构造函数也可以让你拥有最终依赖。
标签: java spring constructor-injection
什么时候在Spring中使用构造函数注入?
我听说在使用组件之前绝对必须拥有依赖类的实例时,构造函数注入特别有用。但这是什么意思?
谁能在以下时刻用一些简单的例子来解释我:
【问题讨论】:
标签: java spring constructor-injection
正确的方法是尽可能使用构造函数注入。多亏了这一点,什么是对象依赖关系很清楚,如果你不提供所有需要的东西,你就无法创建一个。
如下使用构造函数注入。
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 确保您不使用空值代替真实对象。当您使用 setter 注入或字段注入时,您的 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
对于所有非可选依赖项,您可以使用 setter 注入。 阅读 Oliver Gierke(Spring Data 负责人)博客的更多信息:http://olivergierke.de/2013/11/why-field-injection-is-evil/
15.01.2019 更新
从 Spring 4.3 开始,如果只有单个构造函数,则无需在构造函数上放置 @Autowired 注释。
【讨论】:
final 字段的有用性,但Assert.notNull 可以在setter 中轻松完成。 API 示例只有在有人愚蠢地尝试手动构建 bean 时才会发生。哪个无论如何都不可能。
Assert.notNull 也可以在 setter 中完成 - 我发布了完整示例,说明我认为 Java 类在构造方面应该是什么样子。如果你的类是 public 并且你想构建好的 API,你应该知道它也可以在 Spring 上下文之外使用——简单的例子是单元测试。