FastAPI快速入门P2:与SpringBoot比较

欢迎来到啾啾的博客🐱。

记录学习点滴。分享工作思考和实用技巧,偶尔也分享一些杂谈💬。

有很多很多不足的地方,欢迎评论交流,感谢您的阅读和评论😄。

目录

  • 引言
  • [1 FastAPI事件管理](#1 FastAPI事件管理)
  • [2 类的使用](#2 类的使用)
    • [2.1 初始化方法对比](#2.1 初始化方法对比)
    • [2.2 Pydantic的构造](#2.2 Pydantic的构造)
  • [3 依赖管理](#3 依赖管理)
  • [4 类方法和静态方法](#4 类方法和静态方法)
    • [4.1 @classmethod](#4.1 @classmethod)

引言

在之前的《FastAPI快速入门》中,我们对服务器搭建、依赖注入、接口定义与Pydantic模型有了基本了解。本篇继续深入FastAPI的核心机制,并与Java生态的SpringBoot进行对比,帮助Java开发者快速建立技术映射。

1 FastAPI事件管理

FastAPI 提供了 startup 和 shutdown 事件来处理应用启动和关闭时的逻辑,类似于 Spring Boot 的ApplicationRunner@PreDestroy

不过, on_event 在较新版本中已被弃用,推荐使用 lifespan 处理应用生命周期事件。

python 复制代码
from contextlib import asynccontextmanager
from fastapi import FastAPI

# 现代 lifespan 处理方式
@asynccontextmanager
async def lifespan(app: FastAPI):
    # 启动逻辑 - 类似 @PostConstruct
    print("🚀 应用启动:数据库连接池初始化")
    cache = {"hot_items": load_hot_data()}
    
    yield cache  # 将资源传递给路由,即赋值给app.state
    
    # 关闭逻辑 - 类似 @PreDestroy
    print("🛑 应用关闭:释放数据库连接池")
    cache.clear()

app = FastAPI(lifespan=lifespan)  # 注入 lifespan

@app.get("/items")
async def get_items():
    return app.state["hot_items"]  # 直接使用初始化资源

连接池示例

python 复制代码
@asynccontextmanager
async def lifespan(app: FastAPI):
    # 初始化 PostgreSQL 连接池
    app.state.db_pool = await asyncpg.create_pool(
        dsn=os.getenv("DB_DSN"),
        min_size=5,
        max_size=20
    )
    
    # 初始化 Redis 客户端
    app.state.redis = await aioredis.from_url(
        "redis://localhost", 
        encoding="utf-8",
        decode_responses=True
    )
    
    yield
    
    # 资源清理
    await app.state.db_pool.close()
    await app.state.redis.close()

对比SpringBoot

java 复制代码
// Spring Boot 等效实现
@SpringBootApplication
public class DemoApp implements ApplicationRunner {
    
    @Autowired
    private DataSource dataSource;
    
    @PreDestroy
    public void onExit() {
        System.out.println("🛑 释放资源");
    }
    
    @Override
    public void run(ApplicationArguments args) {
        System.out.println("🚀 初始化完成");
    }
}

FastAPI采用显式事件注册,SpringBoot通过接口/注解实现,后者更符合Java的约定优于配置原则。

特性 FastAPI (lifespan) Spring Boot
事件类型 异步上下文管理器 接口实现 + 注解
资源传递 yield 返回 → 直接注入路由 通过 ApplicationContext
错误处理 自带 try/finally 语义 需手动实现销毁逻辑
依赖注入 通过 app.state 访问 @Autowired 自动装配
多阶段初始化 单入口统一管理 多种初始化接口可选

2 类的使用

2.1 初始化方法对比

Python中有__new____init__方法可以用于在对象实例创建时执行一些操作。

python 复制代码
class Service:
    def __new__(cls):
        print("1. 分配内存 → 类似Java的new关键字")
        return super().__new__(cls)
    
    def __init__(self):
        print("2. 初始化属性 → 类似Java的构造函数")
        self.cache = {}

__new__方法比__init__先调用。

Java等效实现如下:

java 复制代码
public class Service {
    private Map<String, Object> cache;
    
    public Service() {
        System.out.println("构造函数初始化");
        this.cache = new HashMap<>();
    }
}
  • cls 与 self
    cls代表类本身。在调用类方法时,Python会自动将类对象作为第一个参数传递给方法。通过 cls 能够访问和修改类的属性,还能创建类的实例。
    self 代表类的实例对象。在调用实例方法时,Python 会自动将实例对象作为第一个参数传递给方法。借助 self 可以访问和修改实例的属性和方法。

2.2 Pydantic的构造

Pydantic模型是默认支持全参构造,等效于@NoArgsConstructor+@AllArgsConstructor的。

且可以通过关键字或字典解包,所以不会有Java的构造函数参数膨胀问题。

python 复制代码
from pydantic import BaseModel

class User(BaseModel):
    name: str
    age: int

# 构造方式1:关键字参数
user = User(name="Alice", age=30) # 自动触发类型验证错误

# 构造方式2:字典解包
data = {"name": "Alice", "age": 30}
user = User(**data)

SpringBoot等效

java 复制代码
// Lombok简化构造
@Data 
@AllArgsConstructor 
public class UserDTO {
    private Long id;
    private String name;
    private String email;
}

3 依赖管理

使用Spring框架时,对象交由框架处理,默认单例,且可以做到复杂的依赖管理。

FastAPI的依赖系统轻量但强大,也支持函数/类级别注入:

python 复制代码
from fastapi import Depends

def get_db_session():
    print("创建DB会话 → 类似Spring的@Bean")
    yield session  # 通过yield实现资源清理
    print("关闭DB会话")

@app.get("/users")
def get_users(db = Depends(get_db_session)):
    return db.query(User).all()

类似于SpringBoot

java 复制代码
@RestController
public class UserController {
    
    private final UserRepository repo;  // 构造器注入
    
    public UserController(UserRepository repo) {
        this.repo = repo;
    }
    
    @GetMapping("/users")
    public List<User> getUsers() {
        return repo.findAll();
    }
}

@Repository  // 自动装配
public interface UserRepository extends JpaRepository<User, Long> {}

核心差异

特性 FastAPI Spring Boot
作用域 函数级控制 完整的Bean作用域
生命周期 显式yield管理 容器自动管理
配置复杂度 低(Python动态特性) 高(需学习Spring生态)
AOP支持 有限(通过中间件) 完善(@Aspect等)

4 类方法和静态方法

4.1 @classmethod

使用装饰器 @classmethod装饰的类和Java中的静态方法一样,可以直接通过类名调用。

不同的是@classmethod装饰的方法有默认入参cls。

python 复制代码
class Validator:
    @classmethod
    def validate_email(cls, email: str) -> bool:
        return "@" in email  # cls可访问类属性

# 直接类调用 → 类似Java静态方法
Validator.validate_email("test@ex.com")

Java等效如下:

java 复制代码
public class Validator {
    public static boolean validateEmail(String email) {
        return email.contains("@");
    }
}

关键区别 :Python的类方法自动获取cls参数,可访问类状态,而Java静态方法无this/cls概念。