refactor(plugin_system): 将依赖检查逻辑从插件基类移至插件管理器
将插件的Python包依赖和插件间依赖的检查逻辑,从各个插件实例的初始化阶段 (`PluginBase`),统一前置到插件模块加载阶段 (`PluginManager`)。 这一重构有以下好处: - **提前失败 (Fail-fast)**:在加载插件模块时立即检查依赖,如果依赖不满足,则直接跳过该插件的加载和实例化,避免了不必要的资源消耗和后续的运行时错误。 - **职责单一**: `PluginManager` 负责插件的发现、加载和依赖管理,而 `PluginBase` 更专注于插件自身的业务逻辑和生命周期,使得代码结构更清晰。 - **配置中心化**: 依赖关系现在统一在 `__plugin_meta__` 中声明,而不是分散在插件类的属性中,提高了可维护性。 - **简化插件实现**: 插件开发者不再需要在插件类中定义 `dependencies` 和 `python_dependencies` 属性,只需在 `__init__.py` 中声明元数据即可。
This commit is contained in:
@@ -323,6 +323,33 @@ class PluginManager:
|
||||
init_module = module_from_spec(init_spec)
|
||||
init_spec.loader.exec_module(init_module)
|
||||
|
||||
# --- 在这里进行依赖检查 ---
|
||||
if hasattr(init_module, "__plugin_meta__"):
|
||||
metadata = getattr(init_module, "__plugin_meta__")
|
||||
from src.plugin_system.utils.dependency_manager import get_dependency_manager
|
||||
|
||||
dependency_manager = get_dependency_manager()
|
||||
|
||||
# 1. 检查Python依赖
|
||||
if metadata.python_dependencies:
|
||||
success, errors = dependency_manager.check_and_install_dependencies(
|
||||
metadata.python_dependencies, metadata.name
|
||||
)
|
||||
if not success:
|
||||
error_msg = f"Python依赖检查失败: {', '.join(errors)}"
|
||||
self.failed_plugins[plugin_name] = error_msg
|
||||
logger.error(f"❌ 插件加载失败: {plugin_name} - {error_msg}")
|
||||
return None # 依赖检查失败,不加载该模块
|
||||
|
||||
# 2. 检查插件依赖
|
||||
if not self._check_plugin_dependencies(metadata):
|
||||
error_msg = f"插件依赖检查失败: 请确保依赖 {metadata.dependencies} 已正确安装并加载。"
|
||||
self.failed_plugins[plugin_name] = error_msg
|
||||
logger.error(f"❌ 插件加载失败: {plugin_name} - {error_msg}")
|
||||
return None # 插件依赖检查失败
|
||||
|
||||
# --- 依赖检查逻辑结束 ---
|
||||
|
||||
# 然后加载 plugin.py
|
||||
spec = spec_from_file_location(module_name, plugin_file)
|
||||
if spec is None or spec.loader is None:
|
||||
@@ -335,7 +362,8 @@ class PluginManager:
|
||||
|
||||
# 将 __plugin_meta__ 从 init_module 附加到主模块
|
||||
if init_module and hasattr(init_module, "__plugin_meta__"):
|
||||
setattr(module, "__plugin_meta__", getattr(init_module, "__plugin_meta__"))
|
||||
metadata = getattr(init_module, "__plugin_meta__")
|
||||
setattr(module, "__plugin_meta__", metadata)
|
||||
|
||||
logger.debug(f"插件模块加载成功: {plugin_file} -> {plugin_name} ({plugin_dir})")
|
||||
return module
|
||||
@@ -346,6 +374,20 @@ class PluginManager:
|
||||
self.failed_plugins[plugin_name if "plugin_name" in locals() else module_name] = error_msg
|
||||
return None
|
||||
|
||||
def _check_plugin_dependencies(self, plugin_meta: PluginMetadata) -> bool:
|
||||
"""检查插件的插件依赖"""
|
||||
dependencies = plugin_meta.dependencies
|
||||
if not dependencies:
|
||||
return True
|
||||
|
||||
for dep_name in dependencies:
|
||||
# 检查依赖的插件类是否已注册
|
||||
if dep_name not in self.plugin_classes:
|
||||
logger.error(f"插件 '{plugin_meta.name}' 缺少依赖: 插件 '{dep_name}' 未找到或加载失败。")
|
||||
return False
|
||||
logger.debug(f"插件 '{plugin_meta.name}' 的所有依赖都已找到。")
|
||||
return True
|
||||
|
||||
# == 显示统计与插件信息 ==
|
||||
|
||||
def _show_stats(self, total_registered: int, total_failed_registration: int):
|
||||
|
||||
Reference in New Issue
Block a user