在 FastAPI 中,使用 类 和 依赖注入函数 都可以实现依赖注入,但它们的设计方式、适用场景和生命周期管理有所不同。以下是它们的区别以及各自的应用场景:
1. 函数依赖注入
函数依赖注入是最常见的一种方式,通过 Depends
来声明依赖,FastAPI 会自动调用这些函数并注入返回的对象。
特点:
- 轻量级:函数依赖注入通常比较简洁,适用于处理简单的依赖项,比如数据库连接、外部 API 客户端等。
- 请求级别的实例:函数依赖项在每次请求时都会被实例化,适用于需要频繁创建和销毁的资源(例如数据库连接)。
- 自动清理:依赖项通常是按请求生命周期管理的,FastAPI 会在请求结束时自动清理资源(例如关闭数据库连接)。
应用场景:
- 数据库连接:每个请求可能需要一个独立的数据库连接(例如,MySQL、PostgreSQL)。
- API 客户端:例如,每次请求都需要调用外部 API,创建一个新的 API 客户端连接。
- 请求级缓存:某些缓存是基于请求的,生命周期较短。
示例:
|
|
2. 类依赖注入
类依赖注入方式是将依赖项封装为类对象,通常用于需要共享状态或较长生命周期的服务。FastAPI 会在请求开始时为该类创建一个实例,随后可以通过类的实例方法提供各种功能。
特点:
- 共享状态:类依赖通常会被设计为一个具有共享状态的对象,可以在类的多个方法之间共享数据。适用于需要在多个请求之间共享状态的服务。
- 适用于复杂的逻辑和服务:如果一个服务需要保存状态,或者需要初始化复杂的资源(如数据库连接池、外部服务连接等),类封装会比简单的函数更加清晰和合适。
- 长生命周期:类的实例可以跨请求存在(可以通过应用启动时创建),因此它更适用于那些具有长生命周期的服务。
应用场景:
- 配置服务:应用级别的配置,通常只在启动时创建,整个生命周期中不会改变。
- 外部服务客户端:如外部 API 客户端或某些大型的外部服务连接(例如,消息队列的连接池)。
- 状态管理服务:需要在多次请求中共享状态的信息(例如,缓存服务、认证服务等)。
示例:
|
|
类与函数依赖注入的主要区别
特性 | 类依赖注入 | 函数依赖注入 |
---|---|---|
实例化时机 | FastAPI 会在请求开始时创建类的实例。 | 每个请求都会调用依赖函数并创建新的实例。 |
状态共享 | 类的实例可以在多个请求之间共享状态。 | 通常每次请求都会创建新的实例,无法共享状态。 |
适用复杂度 | 适用于需要复杂逻辑和状态的服务(如数据库连接池、配置管理)。 | 适用于轻量级服务,如数据库连接或外部 API 客户端。 |
生命周期 | 类的实例可以跨请求存在,适用于长期存在的服务。 | 每次请求都创建新实例,适用于短生命周期依赖。 |
可测试性 | 类实例通常更容易测试(通过模拟类的实例)。 | 依赖函数也可以很容易地模拟和测试。 |
何时使用类依赖注入?
- 共享服务:如果你需要一个在多个请求之间共享的服务,如数据库连接池、配置管理或缓存服务。
- 复杂逻辑:当你的依赖项包含多个方法或复杂的初始化逻辑时,类会是一个好的选择。
- 持久化的状态:类依赖可以保存一些状态并在多个请求之间共享,这在需要多个请求共用某些信息时非常有用(如认证信息、缓存状态等)。
何时使用函数依赖注入?
- 轻量级服务:如果你的依赖项很简单,并且每个请求都有不同的实例(如数据库连接),使用函数依赖注入更加简单和直接。
- 无状态的服务:当服务不需要保存任何状态,或者每个请求都需要创建新实例时,函数依赖注入更为合适。
- 简化的服务管理:函数依赖注入适合那些只需创建一次并简单使用的服务,不需要复杂的构造函数和多种方法。
总结
- 函数依赖注入:适合处理短生命周期、无状态的依赖项,如数据库连接、外部 API 客户端、短期的服务等。
- 类依赖注入:适合需要共享状态、较复杂逻辑、长生命周期的服务,如数据库连接池、外部服务的客户端、全局配置服务等。
根据你的需求选择合适的方式来实现依赖注入,通常函数依赖注入更适合简单和请求级别的资源,而类依赖注入则适合需要跨请求共享状态或者有复杂逻辑的服务。