A lightweight, high-performance async IoC container
Project description
Async IoC Framework
一个轻量级、高性能的异步 IoC 容器,专为现代 Python 异步应用设计。提供依赖注入、配置管理、生命周期回调、定时任务、事务管理、事件驱动、条件注册等特性,语法与 Spring 框架高度相似,Java 开发者可以无缝迁移。
特性
-
依赖注入 – 基于类型注解的自动注入,支持构造函数、List[T]、Set[T]、Optional[T]
-
配置管理 – @Value 注解注入配置值,支持嵌套键与默认值
-
组件生命周期 – @PostConstruct / @PreDestroy,支持同步/异步方法
-
环境隔离 – @Profile + active_profiles,按环境启用/禁用组件
-
优先级与消歧义 – @Primary 指定主 Bean,@Qualifier 按名称注入
-
懒加载 – @Component(lazy=True),按需创建实例
-
定时任务 – @Task 支持固定间隔、Cron 表达式、动态间隔函数
-
声明式事务 – @transactional 自动管理数据库会话与事务,支持传播(复用上层事务)
-
事件驱动 – @EventListener + EventPublisher,松散耦合的同步/异步事件处理
-
条件注册 – @Component(condition=...) 根据配置、类存在性等条件动态注册 Bean
-
模块扫描 – scan_directory 自动导入组件,无需手动注册
-
异步安全 – 基于 contextvars 的会话传递,同一调用链共享同一会话/事务
-
优雅关闭 – 支持信号处理(SIGINT/SIGTERM),自动清理资源
安装
从源码安装
git clone https://github.com/yourname/async-ioc-framework.git
cd async-ioc-framework
pip install -e .
可选依赖
数据库支持:pip install -e .[mysql](自动包含 SQLAlchemy 和对应驱动)
快速开始
- 定义组件
from ioc import Component, PostConstruct
@Component
class Repository:
@PostConstruct
async def init(self):
print("Repository ready")
- 依赖注入
@Component
class UserService:
def __init__(self, repo: Repository): # 构造函数自动注入
self.repo = repo
- 配置注入(config.yaml)
app_name: MyApp
database:
type: mysql
url: mysql://localhost/test
username: root
password: pass123
timeout: 30
from ioc import Component, Value, Annotated
@Component
class ConfigConsumer:
def __init__(
self,
name: Annotated[str, Value("${app_name}")],
db_url: Annotated[str, Value("${database.url:default.db}")],
timeout: Annotated[int, Value("${timeout:10}")],
):
self.name = name
self.db_url = db_url
self.timeout = timeout
- 启动容器
import asyncio
from ioc import ApplicationContext
async def main():
ApplicationContext.initialize("config.yaml")
await ApplicationContext.refresh()
service = ApplicationContext.get_bean(UserService)
# 运行你的业务...
await ApplicationContext.close()
asyncio.run(main())
- 使用启动辅助函数(推荐)
from ioc import run_async
if __name__ == "__main__":
asyncio.run(run_async("config.yaml", "/path/to/project", modules=["my_service"]))
核心概念详解
组件注册
@Component 支持以下参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| name | str | Bean 名称(默认类名小写) |
| priority | int | 创建顺序(数字越小越先) |
| primary | bool | 类型匹配时的首选 Bean |
| profile | str | List[str] 需要激活的 profile |
| lazy | bool | 延迟到第一次使用时创建 |
| condition | Condition | 条件注册,满足条件才创建 |
@Component(name="userRepo", priority=10, primary=True, profile="dev", lazy=False)
class UserRepository:
pass
依赖注入
容器根据构造函数参数类型自动注入:
@Component
class OrderService:
def __init__(self, user_repo: UserRepository, logger: Logger):
self.user_repo = user_repo
self.logger = logger
-
集合注入: List[Service] 或 Set[Service] 会注入所有匹配类型的 Bean。
-
可选依赖: Optional[Service] 允许依赖不存在时注入 None。
-
按名称注入: Annotated[Service, Qualifier("beanName")]。
-
配置值注入: Annotated[str, Value("${key:default}")]。
生命周期回调
-
@PostConstruct: 实例化且依赖注入完成后执行(同步/异步均可)。
-
@PreDestroy: 容器关闭前执行,用于资源释放(同步/异步均可)。
@Component
class ConnectionPool:
@PostConstruct
async def init(self):
await self.connect()
@PreDestroy
async def close(self):
await self.disconnect()
环境隔离(Profile)
配置文件指定激活的 profiles:
active_profiles: ["dev", "local"]
组件按条件注册:
@Component(profile="dev")
class DevDataSource: ...
@Component(profile="prod")
class ProdDataSource: ...
定时任务
使用 @Task 装饰方法(必须是 async def):
@Component
class Scheduler:
@Task(interval=5)
async def run_every_5s(self):
print("每5秒执行")
@Task(cron="0 * * * *")
async def run_hourly(self):
print("每小时执行")
@Task(func=lambda self: self.get_dynamic_interval())
async def dynamic_task(self):
print("动态间隔")
声明式事务(需 SQLAlchemy)
from ioc.ext.data import transactional, get_current_session
@Component
class UserDao:
@transactional
async def create_user(self, name: str):
session = get_current_session()
user = User(name=name)
session.add(user)
# 无异常自动提交,异常自动回滚
事务传播:内层 @transactional 会自动复用外层事务。
事件驱动
from ioc.events import Event, EventListener, EventPublisher
class UserCreated(Event):
def __init__(self, user_id):
self.user_id = user_id
@Component
class UserService:
def __init__(self, publisher: EventPublisher):
self.publisher = publisher
async def create_user(self):
await self.publisher.publish(UserCreated(123))
@Component
class Notifier:
@EventListener(UserCreated)
async def send_email(self, event: UserCreated):
print(f"Send email to user {event.user_id}")
条件注册
内置条件类:
-
OnPropertyCondition(key, having_value=None, match_if_missing=False) – 根据配置属性
-
OnClassExists(class_path) / OnMissingClass(class_path) – 根据类是否存在
-
AllConditions(*conditions) – 所有条件满足
-
AnyCondition(*conditions) – 任一条件满足
-
NotCondition(condition) – 取反
@Component(condition=OnPropertyCondition("cache.enabled", having_value=True))
class CacheService: ...
@Component(condition=AllConditions(
OnPropertyCondition("feature.new.enabled", having_value=True),
OnClassExists("redis.asyncio.Redis")
))
class RedisCache: ...
配置参考
创建 config.yaml:
active_profiles: ["dev"] # 激活的环境
app_name: MyApp
database:
url: sqlite+aiosqlite:///test.db
timeout: 30
debug: true
feature:
new:
enabled: true
modules: # 可选:需要扫描的模块
- services
- dao
在 FastAPI 中集成
from fastapi import FastAPI
from ioc import ApplicationContext
from ioc.ext.data import transactional, get_current_session
app = FastAPI()
@app.on_event("startup")
async def startup():
ApplicationContext.initialize("config.yaml")
await ApplicationContext.refresh()
@app.on_event("shutdown")
async def shutdown():
await ApplicationContext.close()
@app.get("/users/{id}")
async def get_user(id: int):
service = ApplicationContext.get_bean(UserService)
return await service.get_user(id)
API 参考
核心模块 (ioc)
-
ApplicationContext – 静态容器,提供 initialize, refresh, get_bean, close 等方法
-
Component – 组件装饰器
-
Qualifier, Value – 注解类
-
Task, PostConstruct, PreDestroy – 方法装饰器
-
AppConfig – 配置类
-
run – 启动辅助函数
-
条件类 – Condition, OnPropertyCondition, OnClassExists, OnMissingClass, AllConditions, AnyCondition, NotCondition
数据库扩展 (ioc.db)
-
DatabaseFactory – 异步数据库连接池工厂
-
SessionManager – 会话管理器
-
transactional – 事务装饰器
-
get_current_session – 获取当前会话
事件扩展 (ioc.events)
-
Event – 事件基类
-
EventListener – 事件监听器装饰器
-
EventPublisher – 事件发布器
运行测试
bash
直接运行集成测试
python tests/test_container_value.py
使用 pytest(需安装 pytest-asyncio)
pytest tests/
贡献
欢迎提交 Issue 和 Pull Request。
仓库地址
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file async_ioc_framework-0.0.1b0.tar.gz.
File metadata
- Download URL: async_ioc_framework-0.0.1b0.tar.gz
- Upload date:
- Size: 21.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6a417958813ac3ddae63a1cf6ba164e3c4b22cfd6ec5eee9512ea4ba6813bb54
|
|
| MD5 |
a4ae91b6c8446efa8f6f86670407f898
|
|
| BLAKE2b-256 |
2c4b12c680417355999946042b6fa77d4f89a2eb3390b052256100d21f839db1
|
File details
Details for the file async_ioc_framework-0.0.1b0-py3-none-any.whl.
File metadata
- Download URL: async_ioc_framework-0.0.1b0-py3-none-any.whl
- Upload date:
- Size: 25.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b159b24611a68cc634d23f0a9b8eaec42ee948d56562bf2449fe1146349a09e6
|
|
| MD5 |
715ec66d580f0ccbb10ffa9ad7e3e1ee
|
|
| BLAKE2b-256 |
98e67502b4047258cbf2d2107b345df2ea33b766df8a9b80e5fd81bfa8f90600
|