【问题标题】:When to use constructor injection in Spring? [duplicate]什么时候在 Spring 中使用构造函数注入? [复制]
【发布时间】:2015-01-23 18:56:23
【问题描述】:

什么时候在Spring中使用构造函数注入

我听说在使用组件之前绝对必须拥有依赖类的实例时,构造函数注入特别有用。但这是什么意思?

谁能在以下时刻用一些简单的例子来解释我:

  • 使用构造函数注入有什么好处?
  • 什么是动态构造函数注入?

【问题讨论】:

  • 注入构造函数也可以让你拥有最终依赖。

标签: java spring constructor-injection


【解决方案1】:

正确的方法是尽可能使用构造函数注入。多亏了这一点,什么是对象依赖关系很清楚,如果你不提供所有需要的东西,你就无法创建一个。

如下使用构造函数注入。

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 上下文之外使用——简单的例子是单元测试。
  • 任何体面的单元测试框架都可以构造带有模拟依赖的bean。如果您的 bean 应该在任何上下文中工作,那么最好的选择是工厂,而不是显式构造。
  • 面向对象编程的原则之一是确保您的对象始终处于正确状态。通过构造函数注入,您可以显式显示使您的对象实际工作所需的依赖项。这是一个很好的做法,可以让您在未来避免 NPE 和混乱。
  • 我同意这个答案,另外你可以查看这篇对我有很大帮助的文章spring.io/blog/2007/07/11/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-20
  • 2011-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-01
相关资源
最近更新 更多