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