92 lines
3.4 KiB
Python
92 lines
3.4 KiB
Python
|
|
"""framework/bootstrap/dependency_injection.py:依赖注入容器。
|
|||
|
|
|
|||
|
|
本模块是编排层的依赖注入装配点,负责管理 framework 层组件的单例注册
|
|||
|
|
与解析。借鉴 external_systems 的 ``infrastructure/container.py`` 组合根
|
|||
|
|
概念,但采用可变注册表形态以支持启动期分散注册、请求期按需解析。
|
|||
|
|
|
|||
|
|
设计原则:
|
|||
|
|
- framework 层组件(注册中心、EventBus、熔断器等)为应用级单例,跨请求复用
|
|||
|
|
- 请求级组件(被驱动适配器、管道、用例服务)由各自 factory 按请求创建,不进入容器
|
|||
|
|
(如 ``create_driven_adapters(db, outbox_config, redis_client, arq_pool, execution_port)``
|
|||
|
|
与 ``InboundPipeline.create()`` / ``ControlPlanePipeline.create()`` /
|
|||
|
|
``OutboundPipeline.create()``)
|
|||
|
|
- 容器仅负责应用级单例的注册与解析,保持职责单一
|
|||
|
|
- 线程安全:所有读写操作通过 ``threading.Lock`` 串行化
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
from __future__ import annotations
|
|||
|
|
|
|||
|
|
import threading
|
|||
|
|
from typing import Any
|
|||
|
|
|
|||
|
|
from yuxi.channels.contract.errors import InternalError
|
|||
|
|
|
|||
|
|
__all__ = [
|
|||
|
|
"DependencyInjectionContainer",
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
|
|||
|
|
class DependencyInjectionContainer:
|
|||
|
|
"""依赖注入容器。
|
|||
|
|
|
|||
|
|
管理 framework 层组件的单例注册,提供统一的依赖解析入口。
|
|||
|
|
|
|||
|
|
注册形态仅支持单例:由调用方在启动期直接传入已构造实例,
|
|||
|
|
``resolve`` 时原样返回。未注册的接口解析失败抛出 ``InternalError``,
|
|||
|
|
因为这属于装配期编程错误(漏注册),而非客户端请求的资源不存在。
|
|||
|
|
|
|||
|
|
线程安全:所有注册与解析操作通过同一把 ``threading.Lock`` 串行化,
|
|||
|
|
保证并发场景下注册表的读写一致性。
|
|||
|
|
|
|||
|
|
典型用法::
|
|||
|
|
|
|||
|
|
container = DependencyInjectionContainer()
|
|||
|
|
container.registerSingleton(EventBus, InMemoryEventBus())
|
|||
|
|
container.registerSingleton(PluginRegistry, PluginRegistry())
|
|||
|
|
|
|||
|
|
event_bus = container.resolve(EventBus)
|
|||
|
|
plugin_registry = container.resolve(PluginRegistry)
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
def __init__(self) -> None:
|
|||
|
|
"""初始化依赖注入容器。
|
|||
|
|
|
|||
|
|
创建空的单例注册表与互斥锁。
|
|||
|
|
"""
|
|||
|
|
self._singletons: dict[type, Any] = {}
|
|||
|
|
self._lock = threading.Lock()
|
|||
|
|
|
|||
|
|
def registerSingleton(self, interface: type, instance: Any) -> None:
|
|||
|
|
"""注册单例。
|
|||
|
|
|
|||
|
|
将已构造的实例绑定到指定接口类型,后续 ``resolve`` 直接返回该实例。
|
|||
|
|
若同一接口已注册,则覆盖原有绑定。
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
interface: 接口类型(通常为 Protocol 或抽象基类),作为解析键。
|
|||
|
|
instance: 已构造的实例,将作为单例原样返回。
|
|||
|
|
"""
|
|||
|
|
with self._lock:
|
|||
|
|
self._singletons[interface] = instance
|
|||
|
|
|
|||
|
|
def resolve(self, interface: type) -> Any:
|
|||
|
|
"""解析依赖。
|
|||
|
|
|
|||
|
|
返回绑定到该接口的单例实例。若接口未注册,抛出 ``InternalError``。
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
interface: 接口类型(通常为 Protocol 或抽象基类),作为解析键。
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
绑定到该接口的单例实例。
|
|||
|
|
|
|||
|
|
Raises:
|
|||
|
|
InternalError: 该接口未注册单例(装配期漏注册,属编程错误)。
|
|||
|
|
"""
|
|||
|
|
with self._lock:
|
|||
|
|
if interface not in self._singletons:
|
|||
|
|
raise InternalError(
|
|||
|
|
message=f"Dependency not registered: {interface.__name__}",
|
|||
|
|
)
|
|||
|
|
return self._singletons[interface]
|