|
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