依赖注入(Dependency Injection,DI)是一种软件设计模式,它实现了控制反转(Inversion of Control,IoC)的概念,用于减少代码间的耦合,提高组件的可重用性以及可测试性。
在传统的程序设计中,一个对象负责创建和管理它依赖的对象。在依赖注入中,这些依赖关系被反转:对象的依赖项不是由对象本身创建或者查找,而是由外部容器或框架提供。
实现方式
依赖注入可以通过多种方式实现,这里有三个最常见的注入方式:
- 构造器注入:通过对象的构造器传入依赖。
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
// 类的方法使用 userRepository
}
- Setter 注入:通过对象的 setter 方法或其他设置方法注入依赖。
public class UserService {
private UserRepository userRepository;
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
// 类的方法
}
- 接口注入:定义一个包含依赖注入方法的专用接口,需要依赖的对象实现这个接口。
public interface UserRepositorySetter {
void setUserRepository(UserRepository userRepository);
}
public class UserService implements UserRepositorySetter {
private UserRepository userRepository;
@Override
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
// 类的方法
}
优势
-
降低耦合度:依赖注入减少了组件间的直接依赖,使组件之间的耦合度更低,从而使系统更加模块化。
-
提高代码可测试性:由于组件之间耦合度的降低,编写单元测试变得更容易,因为可以通过 Mock 对象等方式注入测试依赖。
-
提高组件可重用性:由于组件不再对于具体实现负责,它们可以在不同的上下文中被重用。
-
更灵活的配置:通过从外部注入依赖,可以很容易地更改组件的依赖设定,从而使得配置更加灵活。
-
更明确的依赖关系:依赖关系通过构造器或 Setter 方法显式表示,使得代码更加清晰,依赖关系更加明确。
-
支持横切关注点(AOP):易于实现各种横切关注点,如事务管理、日志记录等。
Java中的依赖注入通常由框架来提供支持,例如 Spring、Google Guice 和 Jakarta EE(之前称为Java EE),这些框架通过注解和配置文件等方式简化了依赖注入的实现过程。例如,在 Spring 框架中,你可以使用 @Autowired
注解来自动装配依赖关系。