Skip to content

Commit

Permalink
add application event
Browse files Browse the repository at this point in the history
  • Loading branch information
jadbin committed Mar 10, 2020
1 parent 16477a8 commit d6d4628
Show file tree
Hide file tree
Showing 11 changed files with 128 additions and 14 deletions.
8 changes: 4 additions & 4 deletions guniflask/beans/__init__.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
# coding=utf-8

from .bean_registry import *
from .definition import *
from .definition_registry import *
from .errors import *
from .factory import *
from .factory_post_processor import *
from .name_generator import *
from .post_processor import *
from .registry import *

__all__ = (bean_registry.__all__ +
definition.__all__ +
__all__ = (definition.__all__ +
definition_registry.__all__ +
errors.__all__ +
factory.__all__ +
factory_post_processor.__all__ +
name_generator.__all__ +
post_processor.__all__)
post_processor.__all__ +
registry.__all__)
2 changes: 1 addition & 1 deletion guniflask/beans/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from guniflask.beans.errors import BeanTypeNotDeclaredError, BeanTypeNotAllowedError, BeanNotOfRequiredTypeError, \
BeanCreationError, NoUniqueBeanDefinitionError, BeansError
from guniflask.beans.post_processor import BeanPostProcessor
from guniflask.beans.bean_registry import SingletonBeanRegistry
from guniflask.beans.registry import SingletonBeanRegistry

__all__ = ['BeanFactory']

Expand Down
File renamed without changes.
12 changes: 9 additions & 3 deletions guniflask/context/__init__.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
# coding=utf-8

from .annotation import *
from .annotation_config_constants import *
from .annotation_config_registry import *
from .annotation_config_utils import *
from .bean_context import *
from .bean_name_generator import *
from .config_constants import *
from .config_post_processor import *
from .event import *
from .event_listener import *
from .event_publisher import *

__all__ = (annotation.__all__ +
annotation_config_constants.__all__ +
annotation_config_registry.__all__ +
annotation_config_utils.__all__ +
bean_context.__all__ +
bean_name_generator.__all__ +
config_post_processor.__all__)
config_constants.__all__ +
config_post_processor.__all__ +
event.__all__ +
event_listener.__all__ +
event_publisher.__all__)
2 changes: 1 addition & 1 deletion guniflask/context/annotation_config_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from guniflask.beans.definition_registry import BeanDefinitionRegistry
from guniflask.beans.definition import BeanDefinition
from guniflask.context.config_post_processor import ConfigurationClassPostProcessor
from guniflask.context.annotation_config_constants import *
from guniflask.context.config_constants import *

__all__ = ['AnnotationConfigUtils']

Expand Down
31 changes: 29 additions & 2 deletions guniflask/context/bean_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
from guniflask.beans.factory_post_processor import BeanFactoryPostProcessor, BeanDefinitionRegistryPostProcessor
from guniflask.context.annotation_config_registry import AnnotationConfigRegistry
from guniflask.context.annotation_config_registry import AnnotatedBeanDefinitionReader, ModuleBeanDefinitionScanner
from guniflask.context.annotation_config_constants import *
from guniflask.context.config_constants import *
from guniflask.context.event import ApplicationEvent, ContextRefreshedEvent
from guniflask.context.event_listener import ApplicationEventListener
from guniflask.context.event_publisher import ApplicationEventPublisher

__all__ = ['BeanContext', 'AnnotationConfigBeanContext']

Expand All @@ -17,6 +20,8 @@ class BeanContext(BeanFactory):
def __init__(self):
super().__init__()
self._bean_factory_post_processors = []
self._app_listeners = set()
self._app_event_publisher = None

def add_bean_factory_post_processor(self, post_processor: BeanFactoryPostProcessor):
self._bean_factory_post_processors.append(post_processor)
Expand All @@ -29,7 +34,16 @@ def refresh(self):
self._post_process_bean_factory(self)
self._invoke_bean_factory_post_processors(self)
self._register_bean_post_processors(self)
self._init_application_event_publisher(self)
self._register_application_listeners(self)
self._finish_bean_factory_initialization(self)
self._finish_refresh()

def add_application_listener(self, listener: ApplicationEventListener):
self._app_listeners.add(listener)

def publish_event(self, event: ApplicationEvent):
self._app_event_publisher.publish_event(event)

def _post_process_bean_factory(self, bean_factory: BeanFactory):
pass
Expand Down Expand Up @@ -70,14 +84,27 @@ def register_bean_post_processors(factory, post_processors):
post_processor_beans = bean_factory.get_beans_of_type(BeanPostProcessor)
register_bean_post_processors(bean_factory, post_processor_beans)

def _init_application_event_publisher(self, bean_factory: BeanFactory):
self._app_event_publisher = ApplicationEventPublisher(bean_factory)
bean_factory.register_singleton(APPLICATION_EVENT_PUBLISHER, self._app_event_publisher)

def _register_application_listeners(self, bean_factory: BeanFactory):
for listener in self._app_listeners:
self._app_event_publisher.add_application_listener(listener)
bean_names = bean_factory.get_bean_names_for_type(ApplicationEventListener)
for bean_name in bean_names:
self._app_event_publisher.add_application_listener_bean(bean_name)

def _finish_bean_factory_initialization(self, bean_factory: BeanFactory):
bean_factory.pre_instantiate_singletons()

def _finish_refresh(self):
self._app_event_publisher.publish_event(ContextRefreshedEvent(self))


class AnnotationConfigBeanContext(BeanContext, AnnotationConfigRegistry):
def __init__(self):
BeanContext.__init__(self)
self._bean_factory = BeanFactory()
self._reader = AnnotatedBeanDefinitionReader(self)
self._scanner = ModuleBeanDefinitionScanner(self)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# coding=utf-8

__all__ = ['CONFIGURATION_ANNOTATION_PROCESSOR',
__all__ = ['APPLICATION_EVENT_PUBLISHER',
'CONFIGURATION_ANNOTATION_PROCESSOR',
'CONFIGURATION_BEAN_NAME_GENERATOR']

APPLICATION_EVENT_PUBLISHER = '__application_event_publisher'

CONFIGURATION_ANNOTATION_PROCESSOR = '__configuration_annotation_processor'

CONFIGURATION_BEAN_NAME_GENERATOR = '__configuration_bean_name_generator'
4 changes: 2 additions & 2 deletions guniflask/context/config_post_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
from guniflask.beans.definition_registry import BeanDefinitionRegistry
from guniflask.beans.factory_post_processor import BeanDefinitionRegistryPostProcessor
from guniflask.context.bean_name_generator import AnnotationBeanNameGenerator
from guniflask.beans.bean_registry import SingletonBeanRegistry
from guniflask.beans.registry import SingletonBeanRegistry
from guniflask.annotation.annotation_utils import AnnotationUtils
from guniflask.beans.definition import BeanDefinition
from guniflask.context.annotation import Bean, Component, Configuration
from guniflask.annotation.core import AnnotationMetadata
from guniflask.context.annotation_config_constants import *
from guniflask.context.config_constants import *

__all__ = ['ConfigurationClassPostProcessor']

Expand Down
12 changes: 12 additions & 0 deletions guniflask/context/event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# coding=utf-8

__all__ = ['ApplicationEvent', 'ContextRefreshedEvent']


class ApplicationEvent:
def __init__(self, source):
self.source = source


class ContextRefreshedEvent(ApplicationEvent):
pass
14 changes: 14 additions & 0 deletions guniflask/context/event_listener.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# coding=utf-8

from abc import ABCMeta, abstractmethod

from guniflask.context.event import ApplicationEvent

__all__ = ['ApplicationEventListener']


class ApplicationEventListener(metaclass=ABCMeta):

@abstractmethod
def on_application_event(self, application_event: ApplicationEvent):
pass
51 changes: 51 additions & 0 deletions guniflask/context/event_publisher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# coding=utf-8

import inspect

from guniflask.beans.factory import BeanFactory
from guniflask.context.event import ApplicationEvent
from guniflask.context.event_listener import ApplicationEventListener

__all__ = ['ApplicationEventPublisher']


class ApplicationEventPublisher:
def __init__(self, bean_factory: BeanFactory):
self._bean_factory = bean_factory
self._app_listeners = set()
self._app_listener_beans = set()

def add_application_listener(self, listener: ApplicationEventListener):
self._app_listeners.add(listener)

def add_application_listener_bean(self, bean_name: str):
self._app_listener_beans.add(bean_name)

def publish_event(self, event: ApplicationEvent):
for listener in self._get_application_listeners():
assert isinstance(listener, ApplicationEventListener)
accepted_event_type = self._resolve_accepted_event_type(listener.on_application_event)
if accepted_event_type is None or isinstance(event, accepted_event_type):
listener.on_application_event(event)

def _get_application_listeners(self):
for listener in self._app_listeners:
yield listener
for bean_name in self._app_listener_beans:
listener = self._bean_factory.get_bean(bean_name, required_type=ApplicationEventListener)
if listener is not None:
yield listener

def _resolve_accepted_event_type(self, method) -> type:
args_spec = inspect.getfullargspec(method)
args = args_spec.args
event_type_arg = None
if len(args) > 0:
if args[0] in ('self', 'cls'):
if len(args) > 1:
event_type_arg = args[1]
else:
event_type_arg = args[0]
if event_type_arg is not None:
hints = args_spec.annotations
return hints.get(event_type_arg)

0 comments on commit d6d4628

Please sign in to comment.