Skip to content

Python implementation of service locator pattern based on java CDI and ServiceLoader api

License

Notifications You must be signed in to change notification settings

gurcuff91/service-locator

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

service-locator

Light python implementation of service locator pattern based on java CDI and ServiceLoader api.

The service locator pattern is considered by some authors as an anti pattern, which recommend using DI (Dependency Injection), even so Martin Fowler recommends not demonizing it, and use it when it is convenient.

Goals

Getting Started

Prerequisites

Installing

git clone https://github.com/alexescalonafernandez/service-locator.git
cd service-locator
python setup.py sdist
cd dist
pip install service-locator-1.0.tar.gz

Example

# example_repository.py
from service_locator import qualifiers
from service_locator.decorators import ServiceProvider

@ServiceProvider(qualifiers.Repository, 'ExampleRepository')
class ExampleRepository:
    def do_action(self):
        print('do repository action')
# example_controller.py
from service_locator import qualifiers
from service_locator.decorators import ServiceProvider
from service_locator.lookup import ServiceLookup

@ServiceProvider(qualifiers.Controller, 'ExampleController')
class ExampleController:
    def __init__(self, repository=ServiceLookup.proxy(qualifiers.Repository, 'ExampleRepository')):
        self.repository = repository
    
    def do_action(self):
        self.repository.do_action()
# main.py
from service_locator import _command
from service_locator.lookup import ServiceLookup
from service_locator import qualifiers

# set here the main module path for scanning service providers
module_path = 'main module path'

# generate _services.py files with providers configuration
_command.generate_providers_configuration(module_path)


# import _services.py dynamically
_command.populate_service_locator_registry(module_path)

controller = ServiceLookup.lookup(qualifiers.Controller, 'ExampleController')
controller.do_action()

ServiceLookup proxy vs lookup

The proxy method differs from the lookup in that lookup requests an instance from the provider immediately, instead proxy returns a dynamic proxy from the instance so that the instance is only created when any property or method of the instance representing by the proxy is invoked.

It is recommended to use the proxy method in all dependency injections at the parameter level in all the scripts, which uses the @ServiceProvider decorator.

To understand the above, let's analyze what would happen if the controller class is loaded before the repository one. The controller would get a null instance because the service locator registry does not have any provider for the repository.

This means that the order in which the _services.py scripts are loaded is important. The proxy method allows the service locator registry to work correctly regardless of the order in which the scripts are loaded. Otherwise, it would be necessary to implement a topological sort of the scripts to be loaded.

About

Python implementation of service locator pattern based on java CDI and ServiceLoader api

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 100.0%