FastAPI 系列
依赖注入到底省了什么(当前篇)
路径函数不该自己去打开数据库、解析 Token、读配置文件。这些步骤声明成依赖,FastAPI 在调用前解析,调用后清理。省下的不是几行代码,而是可测试的边界。

最简单的依赖
from typing import Annotated
from fastapi import Depends, FastAPI
app = FastAPI()
def get_settings():
return {"env": "dev"}
@app.get("/info")
async def info(settings: Annotated[dict, Depends(get_settings)]):
return settings
Depends(get_settings) 的意思是:先调用 get_settings,把返回值注入参数。同一请求里同一个依赖默认会缓存,不会无意义地执行两遍。
yield:请求前准备,请求后清理
async def get_db():
db = DBSession()
try:
yield db
finally:
db.close()
yield 之前相当于进入 with,之后相当于退出。路径函数跑完、异常抛出后,finally 仍会执行。这是数据库会话、文件句柄、HTTP 客户端的正确位置。
注意:yield 只调用一次。不要在依赖里写两个 yield。
依赖可以再依赖
from typing import Annotated
from fastapi import Depends
from fastapi.security import OAuth2PasswordBearer
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
return fake_decode(token)
async def get_current_active_user(
user: Annotated[User, Depends(get_current_user)],
):
if user.disabled:
raise HTTPException(status_code=400, detail="Inactive user")
return user
路径函数只声明「我需要当前活跃用户」。Token 怎么取、怎么解码,全部藏在依赖链里。鉴权篇会把 JWT 接到这条链上。
什么该进 Depends,什么不该
常见误区
在路径函数里全局用一个 Session
并发请求会串数据。会话按请求创建,用 yield 关闭。
把 Depends 当成服务定位器到处乱调用
依赖树应浅而明确。十层嵌套会让请求变慢,也难读。
忽略 yield 之后的异常
路径函数抛出后,依赖仍可在 except 里 rollback 再 raise。下一篇接数据库时会写完整模式。
小结
Depends 把「请求生命周期里的公共准备」从业务函数里拆走。测试篇会用 dependency_overrides 换掉这些依赖。下一篇把它接到 SQLAlchemy 会话上。
参考资料
依赖注入到底省了什么:Depends、yield 与生命周期
https://lautung.com/archives/fastapi-06-depends
评论