下面這樣的程式碼樣例是一個典型的 nameko 例子
class AddService:
name = 'add_service'
dispatcher = EventDispatcher()
@event_handler('hi_api', 'rubbish')
def receive(self, message: str):
self.dispatcher('to_download', message)
你有好奇過 dispatcher = EventDispatcher()
是怎麼拿到 amqp_uri、connection 這些資訊的嗎?
用你那個貧瘠的大腦好好思考一下,是不是很神奇,是不是驚為天人?
因為這裡面沒有任務的『繼承』
所以是怎麼實現的呢?看看標題就是知道了,必然是跟 nameko 的 Dependency 這個概念有關係。
多說懶得說,自己看原始碼
為了幫你節約時間,我先貼幾個關鍵原始碼
先來看看 EventDispatcher 的繼承關係,理清脈絡
從圖中可知,EventDispatcher 是 DependencyProvider 的子子類,一切的關鍵就是這個 DependencyProvider
讓我們來看看 DependencyProvider 的原始碼
site-packages/nameko/containers.py
class ServiceContainer(object):
def __init__(self, service_cls, config):
self.service_cls = service_cls
self.config = config
self.service_name = get_service_name(service_cls)
self.shared_extensions = {}
self.max_workers = (
config.get(MAX_WORKERS_CONFIG_KEY) or DEFAULT_MAX_WORKERS)
self.serializer, self.accept = serialization.setup(self.config)
self.entrypoints = SpawningSet()
self.dependencies = SpawningSet()
self.subextensions = SpawningSet()
for attr_name, dependency in inspect.getmembers(service_cls,
is_dependency):
bound = dependency.bind(self.interface, attr_name)
self.dependencies.add(bound)
self.subextensions.update(iter_extensions(bound))
for method_name, method in inspect.getmembers(service_cls, is_method):
entrypoints = getattr(method, ENTRYPOINT_EXTENSIONS_ATTR, [])
for entrypoint in entrypoints:
bound = entrypoint.bind(self.interface, method_name)
self.entrypoints.add(bound)
self.subextensions.update(iter_extensions(bound))
self.started = False
self._worker_pool = GreenPool(size=self.max_workers)
self._worker_threads = {}
self._managed_threads = {}
self._being_killed = False
self._died = Event()
關鍵是這部分
for attr_name, dependency in inspect.getmembers(service_cls,
is_dependency):
bound = dependency.bind(self.interface, attr_name)
self.dependencies.add(bound)
self.subextensions.update(iter_extensions(bound))