|
1 |
| -Singleton providers |
2 |
| -------------------- |
| 1 | +Singleton provider |
| 2 | +------------------ |
3 | 3 |
|
4 |
| -.. currentmodule:: dependency_injector.providers |
5 |
| - |
6 |
| -:py:class:`Singleton` provider creates new instance of specified class on |
7 |
| -first call and returns same instance on every next call. |
| 4 | +.. meta:: |
| 5 | + :keywords: Python,DI,Dependency injection,IoC,Inversion of Control,Singleton,Pattern,Example, |
| 6 | + Threads,Multithreading,Scoped |
| 7 | + :description: Singleton provider helps to provide a single object. This page |
| 8 | + demonstrates how to use a Singleton provider. It also provides the example |
| 9 | + of using a singleton and thread locals singleton in the multi-threaded |
| 10 | + environment. |
8 | 11 |
|
9 |
| -Example: |
| 12 | +.. currentmodule:: dependency_injector.providers |
10 | 13 |
|
11 |
| -.. image:: /images/providers/singleton.png |
12 |
| - :width: 80% |
13 |
| - :align: center |
| 14 | +:py:class:`Singleton` provider provides single object. It memorizes the first created object and |
| 15 | +returns it on the rest of the calls. |
14 | 16 |
|
15 | 17 | .. literalinclude:: ../../examples/providers/singleton.py
|
16 | 18 | :language: python
|
| 19 | + :lines: 3- |
17 | 20 |
|
18 |
| -Singleton providers resetting |
19 |
| -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
20 |
| - |
21 |
| -Created and memorized by :py:class:`Singleton` instance can be reset. Reset of |
22 |
| -:py:class:`Singleton`'s memorized instance is done by clearing reference to |
23 |
| -it. Further lifecycle of memorized instance is out of :py:class:`Singleton` |
24 |
| -provider's control and depends on garbage collection strategy. |
25 |
| - |
26 |
| -Example: |
27 |
| - |
28 |
| -.. literalinclude:: ../../examples/providers/singleton_resetting.py |
29 |
| - :language: python |
30 |
| - |
31 |
| -Singleton providers and injections |
32 |
| -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
33 |
| - |
34 |
| -:py:class:`Singleton` provider has same interface as :py:class:`Factory` |
35 |
| -provider, so, all of the rules about injections are the same, as for |
36 |
| -:py:class:`Factory` provider. |
| 21 | +``Singleton`` provider handles an injection of the dependencies the same way like a |
| 22 | +:ref:`factory-provider`. |
37 | 23 |
|
38 | 24 | .. note::
|
39 | 25 |
|
40 |
| - Due that :py:class:`Singleton` provider creates specified class instance |
41 |
| - only on the first call, all injections are done once, during the first |
42 |
| - call. Every next call, while instance has been already created |
43 |
| - and memorized, no injections are done, :py:class:`Singleton` provider just |
44 |
| - returns memorized earlier instance. |
| 26 | + ``Singleton`` provider does dependencies injection only when creates the object. When the object |
| 27 | + is created and memorized ``Singleton`` provider just returns it without applying the injections. |
45 | 28 |
|
46 |
| - This may cause some problems, for example, in case of trying to bind |
47 |
| - :py:class:`Factory` provider with :py:class:`Singleton` provider (provided |
48 |
| - by dependent :py:class:`Factory` instance will be injected only once, |
49 |
| - during the first call). Be aware that such behaviour was made with opened |
50 |
| - eyes and is not a bug. |
| 29 | +Specialization of the provided type and abstract singletons work the same like like for the |
| 30 | +factories: |
51 | 31 |
|
52 |
| - By the way, in such case, :py:class:`Delegate` or |
53 |
| - :py:class:`DelegatedSingleton` provider can be useful |
54 |
| - . It makes possible to inject providers *as is*. Please check out |
55 |
| - `Singleton providers delegation`_ section. |
| 32 | +- :ref:`factory-specialize-provided-type` |
| 33 | +- :ref:`abstract-factory` |
56 | 34 |
|
57 |
| -Singleton providers delegation |
58 |
| -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 35 | +Resetting memorized object |
| 36 | +~~~~~~~~~~~~~~~~~~~~~~~~~~ |
59 | 37 |
|
60 |
| -:py:class:`Singleton` provider could be delegated to any other provider via |
61 |
| -any kind of injection. |
| 38 | +To reset a memorized object you need to call the ``.reset()`` method of the ``Singleton`` |
| 39 | +provider. |
62 | 40 |
|
63 |
| -Delegation of :py:class:`Singleton` providers is the same as |
64 |
| -:py:class:`Factory` providers delegation, please follow |
65 |
| -:ref:`factory_providers_delegation` section for examples (with exception |
66 |
| -of using :py:class:`DelegatedSingleton` instead of |
67 |
| -:py:class:`DelegatedFactory`). |
68 |
| - |
69 |
| -Singleton providers specialization |
70 |
| -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
71 |
| - |
72 |
| -:py:class:`Singleton` provider could be specialized for any kind of needs via |
73 |
| -declaring its subclasses. |
74 |
| - |
75 |
| -Specialization of :py:class:`Singleton` providers is the same as |
76 |
| -:py:class:`Factory` providers specialization, please follow |
77 |
| -:ref:`factory_providers_specialization` section for examples. |
| 41 | +.. literalinclude:: ../../examples/providers/singleton_resetting.py |
| 42 | + :language: python |
| 43 | + :lines: 3- |
| 44 | + :emphasize-lines: 14 |
78 | 45 |
|
79 |
| -Abstract singleton providers |
80 |
| -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 46 | +.. note:: |
| 47 | + Resetting of the memorized object clears the reference to it. Further object's lifecycle is |
| 48 | + managed by the garbage collector. |
81 | 49 |
|
82 |
| -:py:class:`AbstractSingleton` provider is a :py:class:`Singleton` provider that |
83 |
| -must be explicitly overridden before calling. |
| 50 | +Using singleton with multiple threads |
| 51 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
84 | 52 |
|
85 |
| -Behaviour of :py:class:`AbstractSingleton` providers is the same as of |
86 |
| -:py:class:`AbstractFactory`, please follow :ref:`abstract_factory_providers` |
87 |
| -section for examples (with exception of using :py:class:`AbstractSingleton` |
88 |
| -provider instead of :py:class:`AbstractFactory`). |
| 53 | +``Singleton`` provider is NOT thread-safe. You need to explicitly establish a synchronization for |
| 54 | +using the ``Singleton`` provider in the multi-threading application. Otherwise you could trap |
| 55 | +into the race condition problem: ``Singleton`` will create multiple objects. |
89 | 56 |
|
90 |
| -Singleton providers and multi-threading |
91 |
| -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 57 | +There are two thread-safe singleton implementations out of the box: |
92 | 58 |
|
93 |
| -:py:class:`Singleton` provider is NOT thread-safe and should be used in |
94 |
| -multi-threading applications with manually controlled locking. |
| 59 | ++ :py:class:`ThreadSafeSingleton` - is a thread-safe version of a ``Singleton`` provider. You can use |
| 60 | + in multi-threading applications without additional synchronization. |
| 61 | ++ :py:class:`ThreadLocalSingleton` - is a singleton provider that uses thread-locals as a storage. |
| 62 | + This type of singleton will manage multiple objects - the one object for the one thread. |
95 | 63 |
|
96 |
| -:py:class:`ThreadSafeSingleton` is a thread-safe version of |
97 |
| -:py:class:`Singleton` and could be used in multi-threading applications |
98 |
| -without any additional locking. |
| 64 | +.. literalinclude:: ../../examples/providers/singleton_thread_locals.py |
| 65 | + :language: python |
| 66 | + :lines: 3- |
| 67 | + :emphasize-lines: 11,12 |
99 | 68 |
|
100 |
| -Also there could be a need to use thread-scoped singletons and there is a |
101 |
| -special provider for such case - :py:class:`ThreadLocalSingleton`. |
102 |
| -:py:class:`ThreadLocalSingleton` provider creates instance once for each |
103 |
| -thread and returns it on every call. |
| 69 | +Implementing scopes |
| 70 | +~~~~~~~~~~~~~~~~~~~ |
104 | 71 |
|
105 |
| -Example: |
| 72 | +To implement a scoped singleton provider use a ``Singleton`` provider and reset its scope when |
| 73 | +needed. |
106 | 74 |
|
107 |
| -.. literalinclude:: ../../examples/providers/singleton_thread_locals.py |
| 75 | +.. literalinclude:: ../../examples/providers/singleton_scoped.py |
108 | 76 | :language: python
|
109 |
| - |
| 77 | + :lines: 3- |
| 78 | + |
| 79 | +The output should look like this (each request a ``Service`` object has a different address): |
| 80 | + |
| 81 | +.. code-block:: |
| 82 | +
|
| 83 | + * Serving Flask app "singleton_scoped" (lazy loading) |
| 84 | + * Environment: production |
| 85 | + WARNING: This is a development server. Do not use it in a production deployment. |
| 86 | + Use a production WSGI server instead. |
| 87 | + * Debug mode: off |
| 88 | + * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) |
| 89 | + <__main__.Service object at 0x1099a9d90> |
| 90 | + 127.0.0.1 - - [25/Aug/2020 17:33:11] "GET / HTTP/1.1" 200 - |
| 91 | + <__main__.Service object at 0x1099a9cd0> |
| 92 | + 127.0.0.1 - - [25/Aug/2020 17:33:17] "GET / HTTP/1.1" 200 - |
| 93 | + <__main__.Service object at 0x1099a9d00> |
| 94 | + 127.0.0.1 - - [25/Aug/2020 17:33:18] "GET / HTTP/1.1" 200 - |
| 95 | + <__main__.Service object at 0x1099a9e50> |
| 96 | + 127.0.0.1 - - [25/Aug/2020 17:33:18] "GET / HTTP/1.1" 200 - |
| 97 | + <__main__.Service object at 0x1099a9d90> |
| 98 | + 127.0.0.1 - - [25/Aug/2020 17:33:18] "GET / HTTP/1.1" 200 - |
110 | 99 |
|
111 | 100 | .. disqus::
|
0 commit comments