PluginLoader 组件介绍
约 724 字大约 2 分钟
2025-09-26
PluginLoader:插件发现、依赖与生命周期
PluginLoader 负责插件的全生命周期管理:发现、导入、依赖解析、初始化、卸载与重载,以及与 RBAC、事件总线的集成。
总体职责
- 加载内置插件。
- 目录扫描并导入插件模块(支持包或单文件
.py)。 - 自动安装插件依赖(可选,通过插件旁的
requirements.txt或同名.requirements.txt)。 - 构建依赖图并拓扑排序,按依赖顺序加载插件;检查版本约束。
- 为每个插件创建独立的线程池,并在该线程池内执行插件的异步初始化钩子。
- 提供卸载、重载、查询与枚举接口。
- 集成 RBAC:在全局状态中设置
status.global_access_manager。在加载时载入权限数据,卸载时保存权限数据。
发现与导入
入口:load_plugins(plugins_path)
- 先加载内置插件:
SystemManager、UnifiedRegistryPlugin。 - 若未设置
skip_plugin_load,扫描plugins_path下的包与.py文件:- 目录插件需包含
__init__.py - 单文件插件为
xxx.py
- 目录插件需包含
- 对每个候选,若检测到依赖文件:
- 包目录:
<plugin>/requirements.txt - 单文件:
<plugin>.requirements.txt则按行调用包管理器安装(由PackageHelper.ensure实现)。
- 包目录:
- 导入模块后,读取其
__all__中导出的插件类,并筛选出满足接口的类(具有name/version/dependencies)。
依赖与版本检查
通过内部 _DependencyResolver:
- 抽取各插件的
dependencies: Dict[str, version_spec]构建依赖图; - 拓扑排序得到加载顺序;存在环时抛出
PluginCircularDependencyError; - 加载完成后用
SpecifierSet校验版本约束,不满足时抛出PluginVersionError/PluginDependencyError。
初始化与线程模型
为避免阻塞主事件循环,Loader 会在「插件自己的线程池」中执行异步初始化:
- 实例化插件时传入
event_bus/rbac_manager/plugin_loader等依赖; - 把
plugin.__onload__()包装进一个新事件循环并在该线程池中run_until_complete; - 多个插件初始化通过
asyncio.gather并发执行。
卸载时调用 plugin.__unload__();重载时会:
- 调用旧实例的
_reinit_()与on_reload(); - 卸载旧实例;
- reload 模块,重新定位插件类,加载新实例。
关键 API 一览
await load_plugins(path):批量加载(含内置插件)。await load_plugin(PluginClass):单个加载。await unload_plugin(name)/await unload_all():卸载。await reload_plugin(name):重载。list_plugins(obj=False):列出名称或实例。get_plugin(name)/get_metadata(name):查询。
与 EventBus、RBAC 的协作
- 所有插件共享同一个
EventBus实例,插件可在其__onload__中调用event_bus.subscribe(...)订阅事件。 RBACManager被注入并记录到全局状态,用于统一的权限校验;在unload_all时会持久化到config.rbac_path。
开发建议
- 在插件中显式声明
name/version/dependencies,并在__all__中导出插件类。 - 如需第三方依赖,建议使用旁文件
requirements.txt或.requirements.txt,便于自动安装。 - 初始化中的耗时操作会在插件线程池中执行,但仍建议注意超时与异常处理,避免影响总线。
版权所有
版权归属:huan-yp
