FastAPI快速入门P2:与SpringBoot比较

欢迎来到啾啾的博客🐱。
记录学习点滴。分享工作思考和实用技巧,偶尔也分享一些杂谈💬。
有很多很多不足的地方,欢迎评论交流,感谢您的阅读和评论😄。

引言

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

1 FastAPI事件管理

FastAPI 提供了 startup 和 shutdown 事件来处理应用启动和关闭时的逻辑,类似于 Spring Boot 的ApplicationRunner@PreDestroy
不过, on_event 在较新版本中已被弃用,推荐使用 lifespan 处理应用生命周期事件。

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"]  # 直接使用初始化资源

连接池示例

@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

// 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 自动装配
多阶段初始化单入口统一管理多种初始化接口可选

![[FastAPI声明周期.png]]

2 类的使用

2.1 初始化方法对比

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

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

__new__方法比__init__先调用。
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的构造函数参数膨胀问题。

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等效

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

3 依赖管理

使用Spring框架时,对象交由框架处理,默认单例,且可以做到复杂的依赖管理。
FastAPI的依赖系统轻量但强大,也支持函数/类级别注入:

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

@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> {}

核心差异

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

4 类方法和静态方法

4.1 @classmethod

使用装饰器 @classmethod装饰的类和Java中的静态方法一样,可以直接通过类名调用。
不同的是@classmethod装饰的方法有默认入参cls。

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

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

Java等效如下:

public class Validator {
    public static boolean validateEmail(String email) {
        return email.contains("@");
    }
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tataCrayon|啾啾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值