Java中的依赖注入:初学者完全指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:Java中紧耦合的问题

\n\n

想象一下,您正在编写一个用于发送通知的应用程序。在您的NotificationService类中,直接创建了一个EmailSender对象。一切运行良好,直到有一天客户要求添加对短信和推送通知的支持。您将不得不重写NotificationService,修改构造器,添加新的条件。代码变得脆弱、难以测试和扩展。

\n\n

这就是经典的紧耦合(tight coupling)问题。解决方案称为Dependency Injection(依赖注入)——这是Java中关键的设计原则之一,也是Spring等框架的基础。在本文中,我们将用简单的语言解释什么是依赖注入,如何实现它,以及为什么每个专业的Java开发人员都离不开它。

\n\n

用简单的话来说,什么是依赖注入?

\n\n

依赖注入(DI)是一种设计模式,其中对象从外部获取其依赖项,而不是自己创建它们。您不必在类内部编写new EmailSender(),而是通过构造器、setter或接口“注入”一个现成的对象。

\n\n

DI与控制反转(Inversion of Control, IoC)原则密切相关。以前,您的类自己管理依赖项的创建,而现在控制权被移交给外部容器(例如Spring IoC)。

\n\n

DI的主要优点:

\n
    \n
  • 松耦合(loose coupling)——类依赖于抽象,而不是具体实现。
  • \n
  • 简化测试——依赖项可以轻松替换为模拟对象或桩。
  • \n
  • 代码复用——同一个服务可以在不同的上下文中使用。
  • \n
  • 易于维护——更改实现不需要修改消费者类。
  • \n
\n\n

Java中依赖注入的类型

\n\n

在Java中实现依赖注入主要有三种方式。我们通过示例逐一介绍。

\n\n

1. 通过构造器注入(Constructor Injection)

\n\n

这是最常用且推荐的方式。依赖项通过构造器参数传递,并作为类的字段保存(通常是final)。

\n\n
// 发送消息的接口\npublic interface MessageSender {\n    void send(String message, String recipient);\n}\n\n// 具体实现——Email\npublic class EmailSender implements MessageSender {\n    @Override\n    public void send(String message, String recipient) {\n        System.out.println("发送邮件:" + message + " 到 " + recipient);\n    }\n}\n\n// 通过构造器使用DI的服务\npublic class NotificationService {\n    private final MessageSender sender;\n\n    // 依赖项通过构造器注入\n    public NotificationService(MessageSender sender) {\n        this.sender = sender;\n    }\n\n    public void notifyUser(String message, String userEmail) {\n        sender.send(message, userEmail);\n    }\n}\n\n// 使用\npublic class Main {\n    public static void main(String[] args) {\n        MessageSender emailSender = new EmailSender();\n        NotificationService service = new NotificationService(emailSender);\n        service.notifyUser("欢迎!", "user@example.com");\n    }\n}
\n\n

优点:对象在创建时处于完全就绪状态,依赖项不可变(immutable),易于测试。

\n\n

2. 通过setter注入(Setter Injection)

\n\n

依赖项在对象创建后通过setter方法传递。通常用于可选的依赖项。

\n\n
public class NotificationService {\n    private MessageSender sender;\n\n    // 用于注入依赖项的setter\n    public void setSende                

博客

书籍推荐