Java中的依赖注入:从A到Z的实践

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

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

开始课程

Java中的依赖注入:实践

\n\n

依赖注入(DI)是现代Java开发的关键原则之一,是Spring和Jakarta EE等框架的基础。在本文中,我们将探讨什么是依赖注入,为什么需要它,以及最重要的是,如何通过代码示例在实践中应用它。

\n\n

什么是依赖注入,为什么它很重要?

\n\n

依赖注入是一种设计模式,其中对象从外部获取其依赖项,而不是自己创建它们。这实现了控制反转(IoC)原则。类不再自行管理其依赖项,而是将控制权交给外部容器或工厂。

\n\n

想象一下,您正在编写一个发送通知的应用程序。没有DI,您的代码可能如下所示:

\n\n
public class NotificationService {\n    private EmailSender emailSender = new EmailSender();\n\n    public void send(String message) {\n        emailSender.send(message);\n    }\n}
\n\n

问题很明显:NotificationService 与 EmailSender 紧密耦合。如果您想添加SMS或推送通知,则必须重写整个类。使用依赖注入,这个问题就解决了:

\n\n
public class NotificationService {\n    private final MessageSender messageSender;\n\n    // 依赖项通过构造函数传递\n    public NotificationService(MessageSender messageSender) {\n        this.messageSender = messageSender;\n    }\n\n    public void send(String message) {\n        messageSender.send(message);\n    }\n}
\n\n

现在,该类依赖于抽象 MessageSender,而不是具体实现。这使得代码灵活、可测试且可扩展。

\n\n

Java中依赖注入的方式

\n\n

在Java中实现DI主要有三种方式。让我们通过示例逐一介绍。

\n\n

1. 构造函数注入

\n\n

这是最推荐的方式。依赖项通过构造函数参数传递,通常标记为 final。

\n\n
public class UserService {\n    private final UserRepository userRepository;\n    private final EmailService emailService;\n\n    public UserService(UserRepository userRepository, EmailService emailService) {\n        this.userRepository = userRepository;\n        this.emailService = emailService;\n    }\n\n    public void registerUser(User user) {\n        userRepository.save(user);\n        emailService.sendWelcomeEmail(user.getEmail());\n    }\n}
\n\n

优点:

\n
    \n
  • 必需的依赖项清晰可见
  • \n
  • 对象始终处于有效状态
  • \n
  • 非常适合不可变对象
  • \n
  • 易于测试——只需传递模拟对象
  • \n
\n\n

2. Setter注入

\n\n

依赖项在对象创建后通过setter方法设置。

\n\n
public class OrderService {\n    private PaymentGateway paymentGateway;\n\n    public void setPaymentGateway(PaymentGateway paymentGateway) {\n        this.paymentGateway = paymentGateway;\n    }\n\n    public void processOrder(Order order) {\n        paymentGateway.charge(order.getTotal());\n    }\n}
\n\n

何时使用: 用于可选依赖项,或者当依赖项在对象生命周期内可能发生变化时。然而,这种方式使对象变得可变且可预测性较低。

\n\n

3. 字段注入

\n\n

通常与框架一起使用,通过注解实现,例如Spring中的 @Autowired。

\n\n
public class ReportService {\n    @Autowired\n    private DataSource dataSource;\n\n    public Report generateReport() {\n        return dataSource                

博客

书籍推荐