Java中的依赖注入(Dependency Injection):完整指南

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

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

开始课程

引言:什么是依赖注入以及为什么在Java中需要它

在现代Java开发中,代码的整洁性和可测试性是对专业开发者的关键要求之一。Dependency Injection (DI),即依赖注入,是一种设计模式,它能让你的代码实现松耦合、灵活且易于维护。对象不再自行创建其依赖(例如通过new),而是由DI从外部“注入”这些依赖。这是控制反转(IoC)原则的基础部分。

在本文中,我们将解析Dependency Injection在Java中的工作原理,探讨三种主要的实现方式(通过构造器、setter方法和接口),并展示DI如何应用于实际项目中,包括流行的Spring框架。

为什么没有DI你的代码会变得脆弱?

想象一个Car类,它在内部创建了一个引擎:

public class Car {
    private Engine engine;

    public Car() {
        this.engine = new PetrolEngine(); // 硬编码耦合
    }

    public void start() {
        engine.run();
    }
}

这种方式的明显问题包括:

  • 无法复用:你无法轻松地将PetrolEngine替换为ElectricEngine。
  • 测试困难:进行单元测试时,你必须创建真实的引擎,而不是它的模拟对象(mock)。
  • 违反单一职责原则(SRP):Car类不仅负责管理汽车,还负责创建引擎。

Dependency Injection通过将依赖的创建委托给外部代码(容器或其他类)来解决这些问题。

Java中依赖注入的三种方式

在Java中,实现DI主要有三种方法。我们以通知系统为例来逐一说明。

1. 构造器注入(Constructor Injection)

这是最推荐的方式。依赖通过构造器参数传递。这保证了对象总是在有效状态下被创建,并且依赖在创建后不能被修改(不可变性)。

public interface MessageService {
    void sendMessage(String message, String recipient);
}

public class EmailService implements MessageService {
    @Override
    public void sendMessage(String message, String recipient) {
        System.out.println("Email sent to " + recipient + ": " + message);
    }
}

public class NotificationSender {
    private final MessageService messageService;

    // 通过构造器注入依赖
    public NotificationSender(MessageService messageService) {
        this.messageService = messageService;
    }

    public void notifyUser(String userEmail, String msg) {
        messageService.sendMessage(msg, userEmail);
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        MessageService emailService = new EmailService();
        NotificationSender sender = new NotificationSender(emailService); // DI
        sender.notifyUser("user@example.com", "Hello!");
    }
}

2. Setter方法注入(Setter Injection)

适用于可选的依赖,或者依赖可能在对象生命周期内被修改的情况。但是,如果忘记调用setter方法,对象可能会在不完整的状态下被创建。

public class NotificationSender {
    private MessageService messageService;

    // 用于注入依赖的setter方法
    public void setMessageService(MessageService messageService) {
        this.messageService = messageService;
    }

    public void notifyUser(String userEmail, String msg) {
        if (messageService != null) {
            messageService.sendMessage(msg, userEmail);
        } else {
            System.o                

博客

书籍推荐