歡迎來到啾啾的博客🐱。
記錄學習點滴。分享工作思考和實用技巧,偶爾也分享一些雜談💬。
有很多很多不足的地方,歡迎評論交流,感謝您的閱讀和評論😄。
目錄
- 引言
- 1 FastAPI事件管理
- 2 類的使用
- 2.1 初始化方法對比
- 2.2 Pydantic的構造
- 3 依賴管理
- 4 類方法和靜態方法
- 4.1 @classmethod
引言
在之前的《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):# 啟動邏輯 - 類似 @PostConstructprint("🚀 應用啟動:數據庫連接池初始化")cache = {"hot_items": load_hot_data()}yield cache # 將資源傳遞給路由,即賦值給app.state# 關閉邏輯 - 類似 @PreDestroyprint("🛑 應用關閉:釋放數據庫連接池")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 {@Autowiredprivate DataSource dataSource;@PreDestroypublic void onExit() {System.out.println("🛑 釋放資源");}@Overridepublic 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__
方法可以用于在對象實例創建時執行一些操作。
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 BaseModelclass User(BaseModel):name: strage: 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 Dependsdef 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> {}
核心差異:
特性 | FastAPI | Spring Boot |
---|---|---|
作用域 | 函數級控制 | 完整的Bean作用域 |
生命周期 | 顯式yield管理 | 容器自動管理 |
配置復雜度 | 低(Python動態特性) | 高(需學習Spring生態) |
AOP支持 | 有限(通過中間件) | 完善(@Aspect等) |
4 類方法和靜態方法
4.1 @classmethod
使用裝飾器 @classmethod裝飾的類和Java中的靜態方法一樣,可以直接通過類名調用。
不同的是@classmethod裝飾的方法有默認入參cls。
class Validator:@classmethoddef 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概念。