Dependency injection
Programming technique of receiving dependencies
- 45 min read
- 5 chapters
Related on Lably
Through Object (computer science), Function (computer programming) and Client (computing)
- How can a class be independent from the creation of the objects it depends on?
- How can an application and the objects it uses support different configurations?
Dependency injection is often used to keep code in-line with the dependency inversion principle.
In statically typed languages using dependency injection means that a client only needs to declare the interfaces of the services it uses, rather than their concrete implementations, making it easier to change which services are used at runtime without recompiling.
Application frameworks often combine dependency injection with inversion of control. Under inversion of control, the framework first constructs an object (such as a controller), and then passes control flow to it. With dependency injection, the framework also instantiates the dependencies declared by the application object (often in the constructor method's parameters), and passes the dependencies into the object.
Dependency injection implements the idea of "inverting control over the implementations of dependencies", which is why certain Java frameworks generically name the concept "inversion of control" (not to be confused with inversion of control flow).
Roles
Dependency injection involves four roles: services, clients, interfaces, and injectors.
Services and clients
A service is any class which contains useful functionality. In turn, a client is any class which uses services. The services that a client requires are the client's dependencies.
Any object can be a service or a client; the names relate only to the role the objects play in an injection. The same object may even be both a client (it uses injected services) and a service (it is injected into other objects). Upon injection, the service is made part of the client's state, available for use.
Interfaces
Clients should not know how their dependencies are implemented, only their names and API. A service which retrieves emails, for instance, may use the IMAP or POP3 protocols behind the scenes, but this detail is likely irrelevant to calling code that merely wants an email retrieved. By ignoring implementation details, clients do not need to change when their dependencies do.
Injectors
The injector, sometimes also called an assembler, container, provider or factory, introduces services to the client.
The role of injectors is to construct and connect complex object graphs, where objects may be both clients and services. The injector itself may be many objects working together, but must not be the client, as this would create a circular dependency.
Because dependency injection separates how objects are constructed from how they are used, it often diminishes the importance of the new keyword found in most object-oriented languages. Because the framework handles creating services, the programmer tends to only directly construct value objects which represent entities in the program's domain (such as an Employee object in a business app or an Order object in a shopping app).
Analogy
As an analogy, cars can be thought of as services which perform the useful work of transporting people from one place to another. Car engines can require gas, diesel or electricity, but this detail is unimportant to the client—a passenger—who only cares if it can get them to their destination.
Cars present a uniform interface through their pedals, steering wheels and other controls. As such, which engine they were 'injected' with on the factory line ceases to matter and drivers can switch between any kind of car as needed.
Sign in to keep reading
4 more chapters are free with a Lably account.
Advantages and disadvantages
Advantages
A basic benefit of dependency injection is decreased coupling between classes and their dependencies.
By removing a client's knowledge of how its dependencies are implemented, programs become more reusable, testable and maintainable.
This also results in increased flexibility: a client may act on anything that supports the intrinsic interface the client expects.
More generally, dependency injection reduces boilerplate code, since all dependency creation is handled by a singular component.
Finally, dependency injection allows concurrent development. Two developers can independently develop classes that use each other, while only needing to know the interface the classes will communicate through. Plugins are often developed by third-parties that never even talk to developers of the original product.
Testing
Many of dependency injection's benefits are particularly relevant to unit-testing.
For example, dependency injection can be used to externalize a system's configuration details into configuration files, allowing the system to be reconfigured without recompilation. Separate configurations can be written for different situations that require different implementations of components.
Similarly, because dependency injection does not require any change in code behavior, it can be applied to legacy code as a refactoring. This makes clients more independent and are easier to unit test in isolation, using stubs or mock objects, that simulate other objects not under test.
This ease of testing is often the first benefit noticed when using dependency injection.
Disadvantages
Critics of dependency injection argue that it:
- Creates clients that demand configuration details, which can be onerous when obvious defaults are available.
- Makes code difficult to trace because it separates behavior from construction.
- Is typically implemented with reflection or dynamic programming, hindering IDE automation.
- Typically requires more upfront development effort.
- Encourages dependence on a framework.
Types of dependency injection
There are several ways in which a client can receive injected services:
- Constructor injection, where dependencies are provided through a client's class constructor.
- Method Injection, where dependencies are provided to a method only when required for specific functionality.
- Setter injection, where the client exposes a setter method which accepts the dependency.
- Interface injection, where the dependency's interface provides an injector method that will inject the dependency into any client passed to it.
In some frameworks, clients do not need to actively accept dependency injection at all. In Java, for example, reflection can make private attributes public when testing and inject services directly.
Without dependency injection
In the following Java example, the Client class contains a Service member variable initialized in the constructor. The client directly constructs and controls which service it uses, creating a hard-coded dependency.
<span id="mw_Q"></span><span class="kd" id="mw_g">public</span><span class="w" id="mw_w"> </span><span class="kd" id="mwAQA">class</span> <span class="nc" id="mwAQE">Client</span><span class="w" id="mwAQI"> </span><span class="p" id="mwAQM">{</span> <span class="w" id="mwAQQ"> </span><span class="kd" id="mwAQU">private</span><span class="w" id="mwAQY"> </span><span class="n" id="mwAQc">Service</span><span class="w" id="mwAQg"> </span><span class="n" id="mwAQk">service</span><span class="p" id="mwAQo">;</span> <span class="w" id="mwAQs"> </span><span class="n" id="mwAQw">Client</span><span class="p" id="mwAQ0">()</span><span class="w" id="mwAQ4"> </span><span class="p" id="mwAQ8">{</span> <span class="w" id="mwARA"> </span><span class="c1" id="mwARE">// The dependency is hard-coded.</span> <span class="w" id="mwARI"> </span><span class="k" id="mwARM">this</span><span class="p" id="mwARQ">.</span><span class="na" id="mwARU">service</span><span class="w" id="mwARY"> </span><span class="o" id="mwARc">=</span><span class="w" id="mwARg"> </span><span class="k" id="mwARk">new</span><span class="w" id="mwARo"> </span><span class="n" id="mwARs">ExampleService</span><span class="p" id="mwARw">();</span> <span class="w" id="mwAR0"> </span><span class="p" id="mwAR4">}</span> <span class="p" id="mwAR8">}</span>Constructor injection
The most common form of dependency injection is for a class to request its dependencies through its constructor. This ensures the client is always in a valid state, since it cannot be instantiated without its necessary dependencies.
<span id="mwASU"></span><span class="kd" id="mwASY">public</span><span class="w" id="mwASc"> </span><span class="kd" id="mwASg">class</span> <span class="nc" id="mwASk">Client</span><span class="w" id="mwASo"> </span><span class="p" id="mwASs">{</span> <span class="w" id="mwASw"> </span><span class="kd" id="mwAS0">private</span><span class="w" id="mwAS4"> </span><span class="n" id="mwAS8">Service</span><span class="w" id="mwATA"> </span><span class="n" id="mwATE">service</span><span class="p" id="mwATI">;</span> <span class="w" id="mwATM"> </span><span class="c1" id="mwATQ">// The dependency is injected through a constructor.</span> <span class="w" id="mwATU"> </span><span class="n" id="mwATY">Client</span><span class="p" id="mwATc">(</span><span class="n" id="mwATg">Service</span><span class="w" id="mwATk"> </span><span class="n" id="mwATo">service</span><span class="p" id="mwATs">)</span><span class="w" id="mwATw"> </span><span class="p" id="mwAT0">{</span> <span class="w" id="mwAT4"> </span><span class="k" id="mwAT8">if</span><span class="w" id="mwAUA"> </span><span class="p" id="mwAUE">(</span><span class="n" id="mwAUI">service</span><span class="w" id="mwAUM"> </span><span class="o" id="mwAUQ">==</span><span class="w" id="mwAUU"> </span><span class="kc" id="mwAUY">null</span><span class="p" id="mwAUc">)</span><span class="w" id="mwAUg"> </span><span class="p" id="mwAUk">{</span> <span class="w" id="mwAUo"> </span><span class="k" id="mwAUs">throw</span><span class="w" id="mwAUw"> </span><span class="k" id="mwAU0">new</span><span class="w" id="mwAU4"> </span><span class="n" id="mwAU8">IllegalArgumentException</span><span class="p" id="mwAVA">(</span><span class="s" id="mwAVE">"service must not be null"</span><span class="p" id="mwAVI">);</span> <span class="w" id="mwAVM"> </span><span class="p" id="mwAVQ">}</span> <span class="w" id="mwAVU"> </span><span class="k" id="mwAVY">this</span><span class="p" id="mwAVc">.</span><span class="na" id="mwAVg">service</span><span class="w" id="mwAVk"> </span><span class="o" id="mwAVo">=</span><span class="w" id="mwAVs"> </span><span class="n" id="mwAVw">service</span><span class="p" id="mwAV0">;</span> <span class="w" id="mwAV4"> </span><span class="p" id="mwAV8">}</span> <span class="p" id="mwAWA">}</span>Avoiding singletons
Dependency injection can be used to avoid the singleton pattern. The singleton pattern enforces a structural restriction of only one instance of a class, but dependency injection focuses on how dependencies are passed around, avoiding the necessity of objects to look up their own global state.
For example, in the following example, the OrderService is tightly coupled to DatabaseConnection; the database cannot be swapped and a different instance cannot be used.
<span id="mwAW0"></span><span class="c1" id="mwAW4">// a concrete singleton class</span> <span class="kd" id="mwAW8">class</span> <span class="nc" id="mwAXA">DatabaseConnection</span><span class="w" id="mwAXE"> </span><span class="p" id="mwAXI">{</span> <span class="w" id="mwAXM"> </span><span class="kd" id="mwAXQ">private</span><span class="w" id="mwAXU"> </span><span class="kd" id="mwAXY">static</span><span class="w" id="mwAXc"> </span><span class="n" id="mwAXg">DatabaseConnection</span><span class="w" id="mwAXk"> </span><span class="n" id="mwAXo">instance</span><span class="p" id="mwAXs">;</span> <span class="w" id="mwAXw"> </span><span class="kd" id="mwAX0">private</span><span class="w" id="mwAX4"> </span><span class="nf" id="mwAX8">DatabaseConnection</span><span class="p" id="mwAYA">()</span><span class="w" id="mwAYE"> </span><span class="p" id="mwAYI">{</span> <span class="w" id="mwAYM"> </span><span class="c1" id="mwAYQ">// database resource initialization</span> <span class="w" id="mwAYU"> </span><span class="p" id="mwAYY">}</span> <span class="w" id="mwAYc"> </span><span class="kd" id="mwAYg">public</span><span class="w" id="mwAYk"> </span><span class="kd" id="mwAYo">static</span><span class="w" id="mwAYs"> </span><span class="kd" id="mwAYw">synchronized</span><span class="w" id="mwAY0"> </span><span class="n" id="mwAY4">DatabaseConnection</span><span class="w" id="mwAY8"> </span><span class="nf" id="mwAZA">instance</span><span class="p" id="mwAZE">()</span><span class="w" id="mwAZI"> </span><span class="p" id="mwAZM">{</span> <span class="w" id="mwAZQ"> </span><span class="k" id="mwAZU">if</span><span class="w" id="mwAZY"> </span><span class="p" id="mwAZc">(</span><span class="n" id="mwAZg">instance</span><span class="w" id="mwAZk"> </span><span class="o" id="mwAZo">==</span><span class="w" id="mwAZs"> </span><span class="kc" id="mwAZw">null</span><span class="p" id="mwAZ0">)</span><span class="w" id="mwAZ4"> </span><span class="p" id="mwAZ8">{</span> <span class="w" id="mwAaA"> </span><span class="n" id="mwAaE">instance</span><span class="w" id="mwAaI"> </span><span class="o" id="mwAaM">=</span><span class="w" id="mwAaQ"> </span><span class="k" id="mwAaU">new</span><span class="w" id="mwAaY"> </span><span class="n" id="mwAac">DatabaseConnection</span><span class="p" id="mwAag">();</span> <span class="w" id="mwAak"> </span><span class="p" id="mwAao">}</span> <span class="w" id="mwAas"> </span><span class="k" id="mwAaw">return</span><span class="w" id="mwAa0"> </span><span class="n" id="mwAa4">instance</span><span class="p" id="mwAa8">;</span> <span class="w" id="mwAbA"> </span><span class="p" id="mwAbE">}</span> <span class="w" id="mwAbI"> </span><span class="kd" id="mwAbM">public</span><span class="w" id="mwAbQ"> </span><span class="kt" id="mwAbU">void</span><span class="w" id="mwAbY"> </span><span class="nf" id="mwAbc">executeQuery</span><span class="p" id="mwAbg">(</span><span class="n" id="mwAbk">String</span><span class="w" id="mwAbo"> </span><span class="n" id="mwAbs">sql</span><span class="p" id="mwAbw">)</span><span class="w" id="mwAb0"> </span><span class="p" id="mwAb4">{</span> <span class="w" id="mwAb8"> </span><span class="n" id="mwAcA">System</span><span class="p" id="mwAcE">.</span><span class="na" id="mwAcI">out</span><span class="p" id="mwAcM">.</span><span class="na" id="mwAcQ">printf</span><span class="p" id="mwAcU">(</span><span class="s" id="mwAcY">"Executing: %s%n"</span><span class="p" id="mwAcc">);</span> <span class="w" id="mwAcg"> </span><span class="p" id="mwAck">}</span> <span class="p" id="mwAco">}</span> <span class="c1" id="mwAcs">// a tightly-coupled consumer class</span> <span class="kd" id="mwAcw">class</span> <span class="nc" id="mwAc0">OrderService</span><span class="w" id="mwAc4"> </span><span class="p" id="mwAc8">{</span> <span class="w" id="mwAdA"> </span><span class="kd" id="mwAdE">public</span><span class="w" id="mwAdI"> </span><span class="kt" id="mwAdM">void</span><span class="w" id="mwAdQ"> </span><span class="nf" id="mwAdU">placeOrder</span><span class="p" id="mwAdY">(</span><span class="n" id="mwAdc">String</span><span class="w" id="mwAdg"> </span><span class="n" id="mwAdk">orderId</span><span class="p" id="mwAdo">)</span><span class="w" id="mwAds"> </span><span class="p" id="mwAdw">{</span> <span class="w" id="mwAd0"> </span><span class="c1" id="mwAd4">// hardcoded dependency lookup makes this impossible to unit test</span> <span class="w" id="mwAd8"> </span><span class="n" id="mwAeA">DatabaseConnection</span><span class="w" id="mwAeE"> </span><span class="n" id="mwAeI">db</span><span class="w" id="mwAeM"> </span><span class="o" id="mwAeQ">=</span><span class="w" id="mwAeU"> </span><span class="n" id="mwAeY">DatabaseConnection</span><span class="p" id="mwAec">.</span><span class="na" id="mwAeg">instance</span><span class="p" id="mwAek">();</span> <span class="w" id="mwAeo"> </span><span class="n" id="mwAes">db</span><span class="p" id="mwAew">.</span><span class="na" id="mwAe0">executeQuery</span><span class="p" id="mwAe4">(</span><span class="n" id="mwAe8">String</span><span class="p" id="mwAfA">.</span><span class="na" id="mwAfE">format</span><span class="p" id="mwAfI">(</span><span class="s" id="mwAfM">"INSERT INTO orders VALUES ('%s')"</span><span class="p" id="mwAfQ">));</span> <span class="w" id="mwAfU"> </span><span class="p" id="mwAfY">}</span> <span class="p" id="mwAfc">}</span>Dependency injection avoids asking how the database is created, or how many instances exist, and only asks for the Database interface in its constructor:
<span id="mwAf0"></span><span class="c1" id="mwAf4">// an abstract interface</span> <span class="kd" id="mwAf8">interface</span> <span class="nc" id="mwAgA">Database</span><span class="w" id="mwAgE"> </span><span class="p" id="mwAgI">{</span> <span class="w" id="mwAgM"> </span><span class="kt" id="mwAgQ">void</span><span class="w" id="mwAgU"> </span><span class="nf" id="mwAgY">executeQuery</span><span class="p" id="mwAgc">(</span><span class="n" id="mwAgg">String</span><span class="w" id="mwAgk"> </span><span class="n" id="mwAgo">sql</span><span class="p" id="mwAgs">);</span> <span class="p" id="mwAgw">}</span> <span class="c1" id="mwAg0">// implement the concrete class (no singleton logic)</span> <span class="kd" id="mwAg4">class</span> <span class="nc" id="mwAg8">SqlDatabase</span><span class="w" id="mwAhA"> </span><span class="kd" id="mwAhE">implements</span><span class="w" id="mwAhI"> </span><span class="n" id="mwAhM">Database</span><span class="w" id="mwAhQ"> </span><span class="p" id="mwAhU">{</span> <span class="w" id="mwAhY"> </span><span class="nd" id="mwAhc">@Override</span> <span class="w" id="mwAhg"> </span><span class="kd" id="mwAhk">public</span><span class="w" id="mwAho"> </span><span class="kt" id="mwAhs">void</span><span class="w" id="mwAhw"> </span><span class="nf" id="mwAh0">executeQuery</span><span class="p" id="mwAh4">(</span><span class="n" id="mwAh8">String</span><span class="w" id="mwAiA"> </span><span class="n" id="mwAiE">sql</span><span class="p" id="mwAiI">)</span><span class="w" id="mwAiM"> </span><span class="p" id="mwAiQ">{</span> <span class="w" id="mwAiU"> </span><span class="n" id="mwAiY">System</span><span class="p" id="mwAic">.</span><span class="na" id="mwAig">out</span><span class="p" id="mwAik">.</span><span class="na" id="mwAio">printf</span><span class="p" id="mwAis">(</span><span class="s" id="mwAiw">"Executing SQL: %s%n"</span><span class="p" id="mwAi0">,</span><span class="w" id="mwAi4"> </span><span class="n" id="mwAi8">sql</span><span class="p" id="mwAjA">);</span> <span class="w" id="mwAjE"> </span><span class="p" id="mwAjI">}</span> <span class="p" id="mwAjM">}</span> <span class="c1" id="mwAjQ">// the consumer class accepts dependency via constructor injection</span> <span class="kd" id="mwAjU">class</span> <span class="nc" id="mwAjY">OrderService</span><span class="w" id="mwAjc"> </span><span class="p" id="mwAjg">{</span> <span class="w" id="mwAjk"> </span><span class="kd" id="mwAjo">private</span><span class="w" id="mwAjs"> </span><span class="kd" id="mwAjw">final</span><span class="w" id="mwAj0"> </span><span class="n" id="mwAj4">Database</span><span class="w" id="mwAj8"> </span><span class="n" id="mwAkA">db</span><span class="p" id="mwAkE">;</span> <span class="w" id="mwAkI"> </span><span class="c1" id="mwAkM">// The dependency is injected from the outside</span> <span class="w" id="mwAkQ"> </span><span class="kd" id="mwAkU">public</span><span class="w" id="mwAkY"> </span><span class="nf" id="mwAkc">OrderService</span><span class="p" id="mwAkg">(</span><span class="n" id="mwAkk">Database</span><span class="w" id="mwAko"> </span><span class="n" id="mwAks">db</span><span class="p" id="mwAkw">)</span><span class="w" id="mwAk0"> </span><span class="p" id="mwAk4">{</span> <span class="w" id="mwAk8"> </span><span class="k" id="mwAlA">this</span><span class="p" id="mwAlE">.</span><span class="na" id="mwAlI">db</span><span class="w" id="mwAlM"> </span><span class="o" id="mwAlQ">=</span><span class="w" id="mwAlU"> </span><span class="n" id="mwAlY">db</span><span class="p" id="mwAlc">;</span> <span class="w" id="mwAlg"> </span><span class="p" id="mwAlk">}</span> <span class="w" id="mwAlo"> </span><span class="kd" id="mwAls">public</span><span class="w" id="mwAlw"> </span><span class="kt" id="mwAl0">void</span><span class="w" id="mwAl4"> </span><span class="nf" id="mwAl8">placeOrder</span><span class="p" id="mwAmA">(</span><span class="n" id="mwAmE">String</span><span class="w" id="mwAmI"> </span><span class="n" id="mwAmM">orderId</span><span class="p" id="mwAmQ">)</span><span class="w" id="mwAmU"> </span><span class="p" id="mwAmY">{</span> <span class="w" id="mwAmc"> </span><span class="n" id="mwAmg">db</span><span class="p" id="mwAmk">.</span><span class="na" id="mwAmo">executeQuery</span><span class="p" id="mwAms">(</span><span class="n" id="mwAmw">String</span><span class="p" id="mwAm0">.</span><span class="na" id="mwAm4">format</span><span class="p" id="mwAm8">(</span><span class="s" id="mwAnA">"INSERT INTO orders VALUES ('%s')"</span><span class="p" id="mwAnE">,</span><span class="w" id="mwAnI"> </span><span class="n" id="mwAnM">orderId</span><span class="p" id="mwAnQ">));</span> <span class="w" id="mwAnU"> </span><span class="p" id="mwAnY">}</span> <span class="p" id="mwAnc">}</span>Method injection
Dependencies are passed as arguments to a specific method, allowing them to be used only during that method's execution without maintaining a long-term reference. This approach is particularly useful for temporary dependencies or when different implementations are needed for various method calls.
<span id="mwAnw"></span><span class="kd" id="mwAn0">public</span><span class="w" id="mwAn4"> </span><span class="kd" id="mwAn8">class</span> <span class="nc" id="mwAoA">Client</span><span class="w" id="mwAoE"> </span><span class="p" id="mwAoI">{</span> <span class="w" id="mwAoM"> </span><span class="kd" id="mwAoQ">public</span><span class="w" id="mwAoU"> </span><span class="kt" id="mwAoY">void</span><span class="w" id="mwAoc"> </span><span class="nf" id="mwAog">performAction</span><span class="p" id="mwAok">(</span><span class="n" id="mwAoo">Service</span><span class="w" id="mwAos"> </span><span class="n" id="mwAow">service</span><span class="p" id="mwAo0">)</span><span class="w" id="mwAo4"> </span><span class="p" id="mwAo8">{</span> <span class="w" id="mwApA"> </span><span class="k" id="mwApE">if</span><span class="w" id="mwApI"> </span><span class="p" id="mwApM">(</span><span class="n" id="mwApQ">service</span><span class="w" id="mwApU"> </span><span class="o" id="mwApY">==</span><span class="w" id="mwApc"> </span><span class="kc" id="mwApg">null</span><span class="p" id="mwApk">)</span><span class="w" id="mwApo"> </span><span class="p" id="mwAps">{</span> <span class="w" id="mwApw"> </span><span class="k" id="mwAp0">throw</span><span class="w" id="mwAp4"> </span><span class="k" id="mwAp8">new</span><span class="w" id="mwAqA"> </span><span class="n" id="mwAqE">IllegalArgumentException</span><span class="p" id="mwAqI">(</span><span class="s" id="mwAqM">"service must not be null"</span><span class="p" id="mwAqQ">);</span> <span class="w" id="mwAqU"> </span><span class="p" id="mwAqY">}</span> <span class="w" id="mwAqc"> </span><span class="n" id="mwAqg">service</span><span class="p" id="mwAqk">.</span><span class="na" id="mwAqo">execute</span><span class="p" id="mwAqs">();</span> <span class="w" id="mwAqw"> </span><span class="p" id="mwAq0">}</span> <span class="p" id="mwAq4">}</span>Setter injection
By accepting dependencies through a setter method, rather than a constructor, clients can allow injectors to manipulate their dependencies at any time. This offers flexibility, but makes it difficult to ensure that all dependencies are injected and valid before the client is used.
<span id="mwArQ"></span><span class="kd" id="mwArU">public</span><span class="w" id="mwArY"> </span><span class="kd" id="mwArc">class</span> <span class="nc" id="mwArg">Client</span><span class="w" id="mwArk"> </span><span class="p" id="mwAro">{</span> <span class="w" id="mwArs"> </span><span class="kd" id="mwArw">private</span><span class="w" id="mwAr0"> </span><span class="n" id="mwAr4">Service</span><span class="w" id="mwAr8"> </span><span class="n" id="mwAsA">service</span><span class="p" id="mwAsE">;</span> <span class="w" id="mwAsI"> </span><span class="c1" id="mwAsM">// The dependency is injected through a setter method.</span> <span class="w" id="mwAsQ"> </span><span class="kd" id="mwAsU">public</span><span class="w" id="mwAsY"> </span><span class="kt" id="mwAsc">void</span><span class="w" id="mwAsg"> </span><span class="nf" id="mwAsk">setService</span><span class="p" id="mwAso">(</span><span class="n" id="mwAss">Service</span><span class="w" id="mwAsw"> </span><span class="n" id="mwAs0">service</span><span class="p" id="mwAs4">)</span><span class="w" id="mwAs8"> </span><span class="p" id="mwAtA">{</span> <span class="w" id="mwAtE"> </span><span class="k" id="mwAtI">if</span><span class="w" id="mwAtM"> </span><span class="p" id="mwAtQ">(</span><span class="n" id="mwAtU">service</span><span class="w" id="mwAtY"> </span><span class="o" id="mwAtc">==</span><span class="w" id="mwAtg"> </span><span class="kc" id="mwAtk">null</span><span class="p" id="mwAto">)</span><span class="w" id="mwAts"> </span><span class="p" id="mwAtw">{</span> <span class="w" id="mwAt0"> </span><span class="k" id="mwAt4">throw</span><span class="w" id="mwAt8"> </span><span class="k" id="mwAuA">new</span><span class="w" id="mwAuE"> </span><span class="n" id="mwAuI">IllegalArgumentException</span><span class="p" id="mwAuM">(</span><span class="s" id="mwAuQ">"service must not be null"</span><span class="p" id="mwAuU">);</span> <span class="w" id="mwAuY"> </span><span class="p" id="mwAuc">}</span> <span class="w" id="mwAug"> </span><span class="k" id="mwAuk">this</span><span class="p" id="mwAuo">.</span><span class="na" id="mwAus">service</span><span class="w" id="mwAuw"> </span><span class="o" id="mwAu0">=</span><span class="w" id="mwAu4"> </span><span class="n" id="mwAu8">service</span><span class="p" id="mwAvA">;</span> <span class="w" id="mwAvE"> </span><span class="p" id="mwAvI">}</span> <span class="p" id="mwAvM">}</span>Interface injection
With interface injection, dependencies are completely ignorant of their clients, yet still send and receive references to new clients.
In this way, the dependencies become injectors. The key is that the injecting method is provided through an interface.
An assembler is still needed to introduce the client and its dependencies. The assembler takes a reference to the client, casts it to the setter interface that sets that dependency, and passes it to that dependency object which in turn passes a reference to itself back to the client.
For interface injection to have value, the dependency must do something in addition to simply passing back a reference to itself. This could be acting as a factory or sub-assembler to resolve other dependencies, thus abstracting some details from the main assembler. It could be reference-counting so that the dependency knows how many clients are using it. If the dependency maintains a collection of clients, it could later inject them all with a different instance of itself.
<span id="mwAvs"></span><span class="kn" id="mwAvw">package</span><span class="w" id="mwAv0"> </span><span class="nn" id="mwAv4">org.wikipedia.examples</span><span class="p" id="mwAv8">;</span> <span class="kn" id="mwAwA">import</span><span class="w" id="mwAwE"> </span><span class="nn" id="mwAwI">java.util.HashSet</span><span class="p" id="mwAwM">;</span> <span class="kn" id="mwAwQ">import</span><span class="w" id="mwAwU"> </span><span class="nn" id="mwAwY">java.util.Set</span><span class="p" id="mwAwc">;</span> <span class="kd" id="mwAwg">interface</span> <span class="nc" id="mwAwk">ServiceSetter</span><span class="w" id="mwAwo"> </span><span class="p" id="mwAws">{</span> <span class="w" id="mwAww"> </span><span class="kt" id="mwAw0">void</span><span class="w" id="mwAw4"> </span><span class="nf" id="mwAw8">setService</span><span class="p" id="mwAxA">(</span><span class="n" id="mwAxE">Service</span><span class="w" id="mwAxI"> </span><span class="n" id="mwAxM">service</span><span class="p" id="mwAxQ">);</span> <span class="p" id="mwAxU">}</span> <span class="kd" id="mwAxY">class</span> <span class="nc" id="mwAxc">Client</span><span class="w" id="mwAxg"> </span><span class="kd" id="mwAxk">implements</span><span class="w" id="mwAxo"> </span><span class="n" id="mwAxs">ServiceSetter</span><span class="w" id="mwAxw"> </span><span class="p" id="mwAx0">{</span> <span class="w" id="mwAx4"> </span><span class="kd" id="mwAx8">private</span><span class="w" id="mwAyA"> </span><span class="n" id="mwAyE">Service</span><span class="w" id="mwAyI"> </span><span class="n" id="mwAyM">service</span><span class="p" id="mwAyQ">;</span> <span class="w" id="mwAyU"> </span><span class="nd" id="mwAyY">@Override</span> <span class="w" id="mwAyc"> </span><span class="kd" id="mwAyg">public</span><span class="w" id="mwAyk"> </span><span class="kt" id="mwAyo">void</span><span class="w" id="mwAys"> </span><span class="nf" id="mwAyw">setService</span><span class="p" id="mwAy0">(</span><span class="n" id="mwAy4">Service</span><span class="w" id="mwAy8"> </span><span class="n" id="mwAzA">service</span><span class="p" id="mwAzE">)</span><span class="w" id="mwAzI"> </span><span class="p" id="mwAzM">{</span> <span class="w" id="mwAzQ"> </span><span class="k" id="mwAzU">if</span><span class="w" id="mwAzY"> </span><span class="p" id="mwAzc">(</span><span class="n" id="mwAzg">service</span><span class="w" id="mwAzk"> </span><span class="o" id="mwAzo">==</span><span class="w" id="mwAzs"> </span><span class="kc" id="mwAzw">null</span><span class="p" id="mwAz0">)</span><span class="w" id="mwAz4"> </span><span class="p" id="mwAz8">{</span> <span class="w" id="mwA0A"> </span><span class="k" id="mwA0E">throw</span><span class="w" id="mwA0I"> </span><span class="k" id="mwA0M">new</span><span class="w" id="mwA0Q"> </span><span class="n" id="mwA0U">IllegalArgumentException</span><span class="p" id="mwA0Y">(</span><span class="s" id="mwA0c">"service must not be null"</span><span class="p" id="mwA0g">);</span> <span class="w" id="mwA0k"> </span><span class="p" id="mwA0o">}</span> <span class="w" id="mwA0s"> </span><span class="k" id="mwA0w">this</span><span class="p" id="mwA00">.</span><span class="na" id="mwA04">service</span><span class="w" id="mwA08"> </span><span class="o" id="mwA1A">=</span><span class="w" id="mwA1E"> </span><span class="n" id="mwA1I">service</span><span class="p" id="mwA1M">;</span> <span class="w" id="mwA1Q"> </span><span class="p" id="mwA1U">}</span> <span class="p" id="mwA1Y">}</span> <span class="kd" id="mwA1c">class</span> <span class="nc" id="mwA1g">ServiceInjector</span><span class="w" id="mwA1k"> </span><span class="p" id="mwA1o">{</span> <span class="w" id="mwA1s"> </span><span class="kd" id="mwA1w">private</span><span class="w" id="mwA10"> </span><span class="kd" id="mwA14">final</span><span class="w" id="mwA18"> </span><span class="n" id="mwA2A">Set</span><span class="o" id="mwA2E"><</span><span class="n" id="mwA2I">ServiceSetter</span><span class="o" id="mwA2M">></span><span class="w" id="mwA2Q"> </span><span class="n" id="mwA2U">clients</span><span class="w" id="mwA2Y"> </span><span class="o" id="mwA2c">=</span><span class="w" id="mwA2g"> </span><span class="k" id="mwA2k">new</span><span class="w" id="mwA2o"> </span><span class="n" id="mwA2s">HashSet</span><span class="o" id="mwA2w"><></span><span class="p" id="mwA20">();</span> <span class="w" id="mwA24"> </span><span class="kd" id="mwA28">public</span><span class="w" id="mwA3A"> </span><span class="kt" id="mwA3E">void</span><span class="w" id="mwA3I"> </span><span class="nf" id="mwA3M">inject</span><span class="p" id="mwA3Q">(</span><span class="n" id="mwA3U">ServiceSetter</span><span class="w" id="mwA3Y"> </span><span class="n" id="mwA3c">client</span><span class="p" id="mwA3g">)</span><span class="w" id="mwA3k"> </span><span class="p" id="mwA3o">{</span> <span class="w" id="mwA3s"> </span><span class="k" id="mwA3w">this</span><span class="p" id="mwA30">.</span><span class="na" id="mwA34">clients</span><span class="p" id="mwA38">.</span><span class="na" id="mwA4A">add</span><span class="p" id="mwA4E">(</span><span class="n" id="mwA4I">client</span><span class="p" id="mwA4M">);</span> <span class="w" id="mwA4Q"> </span><span class="n" id="mwA4U">client</span><span class="p" id="mwA4Y">.</span><span class="na" id="mwA4c">setService</span><span class="p" id="mwA4g">(</span><span class="k" id="mwA4k">new</span><span class="w" id="mwA4o"> </span><span class="n" id="mwA4s">ExampleService</span><span class="p" id="mwA4w">());</span> <span class="w" id="mwA40"> </span><span class="p" id="mwA44">}</span> <span class="w" id="mwA48"> </span><span class="kd" id="mwA5A">public</span><span class="w" id="mwA5E"> </span><span class="kt" id="mwA5I">void</span><span class="w" id="mwA5M"> </span><span class="nf" id="mwA5Q">switch</span><span class="p" id="mwA5U">()</span><span class="w" id="mwA5Y"> </span><span class="p" id="mwA5c">{</span> <span class="w" id="mwA5g"> </span><span class="k" id="mwA5k">for</span><span class="w" id="mwA5o"> </span><span class="p" id="mwA5s">(</span><span class="n" id="mwA5w">Client</span><span class="w" id="mwA50"> </span><span class="n" id="mwA54">client</span><span class="w" id="mwA58"> </span><span class="p" id="mwA6A">:</span><span class="w" id="mwA6E"> </span><span class="k" id="mwA6I">this</span><span class="p" id="mwA6M">.</span><span class="na" id="mwA6Q">clients</span><span class="p" id="mwA6U">)</span><span class="w" id="mwA6Y"> </span><span class="p" id="mwA6c">{</span> <span class="w" id="mwA6g"> </span><span class="n" id="mwA6k">client</span><span class="p" id="mwA6o">.</span><span class="na" id="mwA6s">setService</span><span class="p" id="mwA6w">(</span><span class="k" id="mwA60">new</span><span class="w" id="mwA64"> </span><span class="n" id="mwA68">AnotherExampleService</span><span class="p" id="mwA7A">());</span> <span class="w" id="mwA7E"> </span><span class="p" id="mwA7I">}</span> <span class="w" id="mwA7M"> </span><span class="p" id="mwA7Q">}</span> <span class="p" id="mwA7U">}</span> <span class="kd" id="mwA7Y">class</span> <span class="nc" id="mwA7c">ExampleService</span><span class="w" id="mwA7g"> </span><span class="kd" id="mwA7k">implements</span><span class="w" id="mwA7o"> </span><span class="n" id="mwA7s">Service</span><span class="w" id="mwA7w"> </span><span class="p" id="mwA70">{}</span> <span class="kd" id="mwA74">class</span> <span class="nc" id="mwA78">AnotherExampleService</span><span class="w" id="mwA8A"> </span><span class="kd" id="mwA8E">implements</span><span class="w" id="mwA8I"> </span><span class="n" id="mwA8M">Service</span><span class="w" id="mwA8Q"> </span><span class="p" id="mwA8U">{}</span>Assembly
The simplest way of implementing dependency injection is to manually arrange services and clients, typically done at the program's root, where execution begins.
<span id="mwA8o"></span><span class="kd" id="mwA8s">public</span><span class="w" id="mwA8w"> </span><span class="kd" id="mwA80">class</span> <span class="nc" id="mwA84">Program</span><span class="w" id="mwA88"> </span><span class="p" id="mwA9A">{</span> <span class="w" id="mwA9E"> </span><span class="kd" id="mwA9I">public</span><span class="w" id="mwA9M"> </span><span class="kd" id="mwA9Q">static</span><span class="w" id="mwA9U"> </span><span class="kt" id="mwA9Y">void</span><span class="w" id="mwA9c"> </span><span class="nf" id="mwA9g">main</span><span class="p" id="mwA9k">(</span><span class="n" id="mwA9o">String</span><span class="o" id="mwA9s">[]</span><span class="w" id="mwA9w"> </span><span class="n" id="mwA90">args</span><span class="p" id="mwA94">)</span><span class="w" id="mwA98"> </span><span class="p" id="mwA-A">{</span> <span class="w" id="mwA-E"> </span><span class="c1" id="mwA-I">// Build the service.</span> <span class="w" id="mwA-M"> </span><span class="n" id="mwA-Q">Service</span><span class="w" id="mwA-U"> </span><span class="n" id="mwA-Y">service</span><span class="w" id="mwA-c"> </span><span class="o" id="mwA-g">=</span><span class="w" id="mwA-k"> </span><span class="k" id="mwA-o">new</span><span class="w" id="mwA-s"> </span><span class="n" id="mwA-w">ExampleService</span><span class="p" id="mwA-0">();</span> <span class="w" id="mwA-4"> </span><span class="c1" id="mwA-8">// Inject the service into the client.</span> <span class="w" id="mwA_A"> </span><span class="n" id="mwA_E">Client</span><span class="w" id="mwA_I"> </span><span class="n" id="mwA_M">client</span><span class="w" id="mwA_Q"> </span><span class="o" id="mwA_U">=</span><span class="w" id="mwA_Y"> </span><span class="k" id="mwA_c">new</span><span class="w" id="mwA_g"> </span><span class="n" id="mwA_k">Client</span><span class="p" id="mwA_o">(</span><span class="n" id="mwA_s">service</span><span class="p" id="mwA_w">);</span> <span class="w" id="mwA_0"> </span><span class="c1" id="mwA_4">// Use the objects.</span> <span class="w" id="mwA_8"> </span><span class="n" id="mwBAA">System</span><span class="p" id="mwBAE">.</span><span class="na" id="mwBAI">out</span><span class="p" id="mwBAM">.</span><span class="na" id="mwBAQ">println</span><span class="p" id="mwBAU">(</span><span class="n" id="mwBAY">client</span><span class="p" id="mwBAc">.</span><span class="na" id="mwBAg">greet</span><span class="p" id="mwBAk">());</span> <span class="w" id="mwBAo"> </span><span class="p" id="mwBAs">}</span><span class="w" id="mwBAw"> </span> <span class="p" id="mwBA0">}</span>Manual construction may be more complex and involve builders, factories, or other construction patterns.
Frameworks
Manual dependency injection is often tedious and error-prone for larger projects, promoting the use of frameworks which automate the process. Manual dependency injection becomes a dependency injection framework once the constructing code is no longer custom to the application and is instead universal. While useful, these tools are not required in order to perform dependency injection.
In Java, a dependency injection framework was historically provided by Java EE under javax.inject; it is now provided by Jakarta EE as jakarta.inject, with the jakarta.inject.Provider<T> interface for obtaining instances of T, and the following annotations:
@Inject, for marking injectable constructors, methods, and fields@Named, for marking a string-based qualifier@Qualifier, for marking qualifier annotations@Scope, for marking scope annotations@Singleton, for marking a type subject to the singleton pattern by the injector
In .NET (such as C#), the Microsoft.Extensions.DependencyInjection library is a bundled framework within .NET.
Some frameworks, like Spring, can use external configuration files to plan program composition:
<span id="mwBE8"></span><span class="kn" id="mwBFA">package</span><span class="w" id="mwBFE"> </span><span class="nn" id="mwBFI">org.wikipedia.examples</span><span class="p" id="mwBFM">;</span> <span class="kn" id="mwBFQ">import</span><span class="w" id="mwBFU"> </span><span class="nn" id="mwBFY">org.springframework.beans.factory.BeanFactory</span><span class="p" id="mwBFc">;</span> <span class="kn" id="mwBFg">import</span><span class="w" id="mwBFk"> </span><span class="nn" id="mwBFo">org.springframework.context.ApplicationContext</span><span class="p" id="mwBFs">;</span> <span class="kn" id="mwBFw">import</span><span class="w" id="mwBF0"> </span><span class="nn" id="mwBF4">org.springframework.context.support.ClassPathXmlApplicationContext</span><span class="p" id="mwBF8">;</span> <span class="kd" id="mwBGA">public</span><span class="w" id="mwBGE"> </span><span class="kd" id="mwBGI">class</span> <span class="nc" id="mwBGM">Injector</span><span class="w" id="mwBGQ"> </span><span class="p" id="mwBGU">{</span> <span class="w" id="mwBGY"> </span><span class="kd" id="mwBGc">public</span><span class="w" id="mwBGg"> </span><span class="kd" id="mwBGk">static</span><span class="w" id="mwBGo"> </span><span class="kt" id="mwBGs">void</span><span class="w" id="mwBGw"> </span><span class="nf" id="mwBG0">main</span><span class="p" id="mwBG4">(</span><span class="n" id="mwBG8">String</span><span class="o" id="mwBHA">[]</span><span class="w" id="mwBHE"> </span><span class="n" id="mwBHI">args</span><span class="p" id="mwBHM">)</span><span class="w" id="mwBHQ"> </span><span class="p" id="mwBHU">{</span> <span class="w" id="mwBHY"> </span><span class="c1" id="mwBHc">// Details about which concrete service to use are stored in configuration separate from the program itself.</span> <span class="w" id="mwBHg"> </span><span class="n" id="mwBHk">BeanFactory</span><span class="w" id="mwBHo"> </span><span class="n" id="mwBHs">beanfactory</span><span class="w" id="mwBHw"> </span><span class="o" id="mwBH0">=</span><span class="w" id="mwBH4"> </span><span class="k" id="mwBH8">new</span><span class="w" id="mwBIA"> </span><span class="n" id="mwBIE">ClassPathXmlApplicationContext</span><span class="p" id="mwBII">(</span><span class="s" id="mwBIM">"Beans.xml"</span><span class="p" id="mwBIQ">);</span> <span class="w" id="mwBIU"> </span><span class="n" id="mwBIY">Client</span><span class="w" id="mwBIc"> </span><span class="n" id="mwBIg">client</span><span class="w" id="mwBIk"> </span><span class="o" id="mwBIo">=</span><span class="w" id="mwBIs"> </span><span class="p" id="mwBIw">(</span><span class="n" id="mwBI0">Client</span><span class="p" id="mwBI4">)</span><span class="w" id="mwBI8"> </span><span class="n" id="mwBJA">beanfactory</span><span class="p" id="mwBJE">.</span><span class="na" id="mwBJI">getBean</span><span class="p" id="mwBJM">(</span><span class="s" id="mwBJQ">"client"</span><span class="p" id="mwBJU">);</span> <span class="w" id="mwBJY"> </span><span class="n" id="mwBJc">System</span><span class="p" id="mwBJg">.</span><span class="na" id="mwBJk">out</span><span class="p" id="mwBJo">.</span><span class="na" id="mwBJs">println</span><span class="p" id="mwBJw">(</span><span class="n" id="mwBJ0">client</span><span class="p" id="mwBJ4">.</span><span class="na" id="mwBJ8">greet</span><span class="p" id="mwBKA">());</span> <span class="w" id="mwBKE"> </span><span class="p" id="mwBKI">}</span> <span class="p" id="mwBKM">}</span>Even with a potentially long and complex object graph, the only class mentioned in code is the entry point, in this case Client. Client has not undergone any changes to work with Spring and remains a POJO. By keeping Spring-specific annotations and calls from spreading out among many classes, the system stays only loosely dependent on Spring.
Examples
Angular
The following example shows an Angular component receiving a greeting service through dependency injection:
<span id="mwBL4"></span><span class="c1" id="mwBL8">// greeter.service.ts</span> <span class="k" id="mwBMA">import</span><span class="w" id="mwBME"> </span><span class="p" id="mwBMI">{</span><span class="w" id="mwBMM"> </span><span class="nx" id="mwBMQ">Injectable</span><span class="p" id="mwBMU">,</span><span class="w" id="mwBMY"> </span><span class="nx" id="mwBMc">inject</span><span class="w" id="mwBMg"> </span><span class="p" id="mwBMk">}</span><span class="w" id="mwBMo"> </span><span class="kr" id="mwBMs">from</span><span class="w" id="mwBMw"> </span><span class="s1" id="mwBM0">'@angular/core'</span><span class="p" id="mwBM4">;</span> <span class="k" id="mwBM8">import</span><span class="w" id="mwBNA"> </span><span class="p" id="mwBNE">{</span><span class="w" id="mwBNI"> </span><span class="nx" id="mwBNM">DOCUMENT</span><span class="w" id="mwBNQ"> </span><span class="p" id="mwBNU">}</span><span class="w" id="mwBNY"> </span><span class="kr" id="mwBNc">from</span><span class="w" id="mwBNg"> </span><span class="s1" id="mwBNk">'@angular/common'</span><span class="p" id="mwBNo">;</span> <span class="k" id="mwBNs">export</span><span class="w" id="mwBNw"> </span><span class="kd" id="mwBN0">interface</span><span class="w" id="mwBN4"> </span><span class="nx" id="mwBN8">IGreeterService</span><span class="w" id="mwBOA"> </span><span class="p" id="mwBOE">{</span> <span class="w" id="mwBOI"> </span><span class="nx" id="mwBOM">greet</span><span class="p" id="mwBOQ">(</span><span class="nx" id="mwBOU">text</span><span class="o" id="mwBOY">:</span><span class="w" id="mwBOc"> </span><span class="kt" id="mwBOg">string</span><span class="p" id="mwBOk">)</span><span class="o" id="mwBOo">:</span><span class="w" id="mwBOs"> </span><span class="ow" id="mwBOw">void</span><span class="p" id="mwBO0">;</span> <span class="p" id="mwBO4">}</span> <span class="kd" id="mwBO8">@Injectable</span><span class="p" id="mwBPA">({</span> <span class="w" id="mwBPE"> </span><span class="nx" id="mwBPI">providedIn</span><span class="o" id="mwBPM">:</span><span class="w" id="mwBPQ"> </span><span class="s1" id="mwBPU">'root'</span> <span class="p" id="mwBPY">})</span> <span class="k" id="mwBPc">export</span><span class="w" id="mwBPg"> </span><span class="kd" id="mwBPk">class</span><span class="w" id="mwBPo"> </span><span class="nx" id="mwBPs">GreeterService</span><span class="w" id="mwBPw"> </span><span class="k" id="mwBP0">implements</span><span class="w" id="mwBP4"> </span><span class="nx" id="mwBP8">IGreeterService</span><span class="w" id="mwBQA"> </span><span class="p" id="mwBQE">{</span> <span class="w" id="mwBQI"> </span><span class="c1" id="mwBQM">// Use inject(DOCUMENT) and access defaultView to get the Window object</span> <span class="w" id="mwBQQ"> </span><span class="k" id="mwBQU">private</span><span class="w" id="mwBQY"> </span><span class="nx" id="mwBQc">window</span><span class="o" id="mwBQg">:</span><span class="w" id="mwBQk"> </span><span class="kt" id="mwBQo">Window</span><span class="w" id="mwBQs"> </span><span class="o" id="mwBQw">=</span><span class="w" id="mwBQ0"> </span><span class="nx" id="mwBQ4">inject</span><span class="p" id="mwBQ8">(</span><span class="nx" id="mwBRA">DOCUMENT</span><span class="p" id="mwBRE">).</span><span class="nx" id="mwBRI">defaultView</span><span class="w" id="mwBRM"> </span><span class="kr" id="mwBRQ">as</span><span class="w" id="mwBRU"> </span><span class="nx" id="mwBRY">Window</span><span class="p" id="mwBRc">;</span> <span class="w" id="mwBRg"> </span><span class="nx" id="mwBRk">greet</span><span class="p" id="mwBRo">(</span><span class="nx" id="mwBRs">text</span><span class="o" id="mwBRw">:</span><span class="w" id="mwBR0"> </span><span class="kt" id="mwBR4">string</span><span class="p" id="mwBR8">)</span><span class="o" id="mwBSA">:</span><span class="w" id="mwBSE"> </span><span class="ow" id="mwBSI">void</span><span class="w" id="mwBSM"> </span><span class="p" id="mwBSQ">{</span> <span class="w" id="mwBSU"> </span><span class="k" id="mwBSY">this</span><span class="p" id="mwBSc">.</span><span class="nb" id="mwBSg">window</span><span class="p" id="mwBSk">.</span><span class="nx" id="mwBSo">alert</span><span class="p" id="mwBSs">(</span><span class="nx" id="mwBSw">text</span><span class="p" id="mwBS0">);</span> <span class="w" id="mwBS4"> </span><span class="p" id="mwBS8">}</span> <span class="p" id="mwBTA">}</span><span id="mwBTM"></span><span class="cm" id="mwBTQ"><!-- my-controller.component.html --></span> <span class="p" id="mwBTU"><</span><span class="nt" id="mwBTY">div</span><span class="p" id="mwBTc">></span> <span class="p" id="mwBTg"><</span><span class="nt" id="mwBTk">button</span> <span class="err" id="mwBTo">(</span><span class="na" id="mwBTs">click</span><span class="err" id="mwBTw">)="</span><span class="na" id="mwBT0">sayHello</span><span class="err" id="mwBT4">()"</span><span class="p" id="mwBT8">></span>Hello<span class="p" id="mwBUA"></</span><span class="nt" id="mwBUE">button</span><span class="p" id="mwBUI">></span> <span class="p" id="mwBUM"></</span><span class="nt" id="mwBUQ">div</span><span class="p" id="mwBUU">></span>
<span id="mwBUg"></span><span class="c1" id="mwBUk">// my-controller.component.ts</span> <span class="k" id="mwBUo">import</span><span class="w" id="mwBUs"> </span><span class="p" id="mwBUw">{</span><span class="w" id="mwBU0"> </span><span class="nx" id="mwBU4">GreeterService</span><span class="w" id="mwBU8"> </span><span class="p" id="mwBVA">}</span><span class="w" id="mwBVE"> </span><span class="kr" id="mwBVI">from</span><span class="w" id="mwBVM"> </span><span class="s1" id="mwBVQ">'./greeter.service.ts'</span><span class="p" id="mwBVU">;</span> <span class="k" id="mwBVY">import</span><span class="w" id="mwBVc"> </span><span class="p" id="mwBVg">{</span><span class="w" id="mwBVk"> </span><span class="nx" id="mwBVo">Component</span><span class="p" id="mwBVs">,</span><span class="w" id="mwBVw"> </span><span class="nx" id="mwBV0">inject</span><span class="w" id="mwBV4"> </span><span class="p" id="mwBV8">}</span><span class="w" id="mwBWA"> </span><span class="kr" id="mwBWE">from</span><span class="w" id="mwBWI"> </span><span class="s1" id="mwBWM">'@angular/core'</span><span class="p" id="mwBWQ">;</span> <span class="kd" id="mwBWU">@Component</span><span class="p" id="mwBWY">({</span> <span class="w" id="mwBWc"> </span><span class="nx" id="mwBWg">selector</span><span class="o" id="mwBWk">:</span><span class="w" id="mwBWo"> </span><span class="s1" id="mwBWs">'app-my-controller'</span><span class="p" id="mwBWw">,</span> <span class="w" id="mwBW0"> </span><span class="nx" id="mwBW4">template</span><span class="o" id="mwBW8">:</span><span class="w" id="mwBXA"> </span><span class="s1" id="mwBXE">'my-controller.component.html'</span> <span class="p" id="mwBXI">})</span> <span class="k" id="mwBXM">export</span><span class="w" id="mwBXQ"> </span><span class="kd" id="mwBXU">class</span><span class="w" id="mwBXY"> </span><span class="nx" id="mwBXc">MyControllerComponent</span><span class="w" id="mwBXg"> </span><span class="p" id="mwBXk">{</span> <span class="w" id="mwBXo"> </span><span class="k" id="mwBXs">private</span><span class="w" id="mwBXw"> </span><span class="nx" id="mwBX0">greeter</span><span class="w" id="mwBX4"> </span><span class="o" id="mwBX8">=</span><span class="w" id="mwBYA"> </span><span class="nx" id="mwBYE">inject</span><span class="p" id="mwBYI">(</span><span class="nx" id="mwBYM">GreeterService</span><span class="p" id="mwBYQ">);</span> <span class="w" id="mwBYU"> </span><span class="nx" id="mwBYY">sayHello</span><span class="p" id="mwBYc">()</span><span class="o" id="mwBYg">:</span><span class="w" id="mwBYk"> </span><span class="ow" id="mwBYo">void</span><span class="w" id="mwBYs"> </span><span class="p" id="mwBYw">{</span> <span class="w" id="mwBY0"> </span><span class="k" id="mwBY4">this</span><span class="p" id="mwBY8">.</span><span class="nx" id="mwBZA">greeter</span><span class="p" id="mwBZE">.</span><span class="nx" id="mwBZI">greet</span><span class="p" id="mwBZM">(</span><span class="s1" id="mwBZQ">'Hello World'</span><span class="p" id="mwBZU">);</span> <span class="w" id="mwBZY"> </span><span class="p" id="mwBZc">}</span> <span class="p" id="mwBZg">}</span>The inject function triggers the injector to create an instance of the GreeterService and its dependencies (in this case, a Document instance to access the window object).
C++
This sample provides an example of constructor injection.
<span id="mwBaQ"></span><span class="k" id="mwBaU">import</span><span class="w" id="mwBaY"> </span><span class="n" id="mwBac">std</span><span class="p" id="mwBag">;</span> <span class="k" id="mwBak">class</span><span class="w" id="mwBao"> </span><span class="nc" id="mwBas">DatabaseConnection</span><span class="w" id="mwBaw"> </span><span class="p" id="mwBa0">{</span> <span class="k" id="mwBa4">public</span><span class="o" id="mwBa8">:</span> <span class="w" id="mwBbA"> </span><span class="kt" id="mwBbE">void</span><span class="w" id="mwBbI"> </span><span class="n" id="mwBbM">connect</span><span class="p" id="mwBbQ">()</span><span class="w" id="mwBbU"> </span><span class="p" id="mwBbY">{</span> <span class="w" id="mwBbc"> </span><span class="n" id="mwBbg">std</span><span class="o" id="mwBbk">::</span><span class="n" id="mwBbo">println</span><span class="p" id="mwBbs">(</span><span class="s" id="mwBbw">"Connecting to database..."</span><span class="p" id="mwBb0">);</span> <span class="w" id="mwBb4"> </span><span class="p" id="mwBb8">}</span> <span class="p" id="mwBcA">};</span> <span class="k" id="mwBcE">class</span><span class="w" id="mwBcI"> </span><span class="nc" id="mwBcM">DatabaseService</span><span class="w" id="mwBcQ"> </span><span class="p" id="mwBcU">{</span> <span class="k" id="mwBcY">private</span><span class="o" id="mwBcc">:</span> <span class="w" id="mwBcg"> </span><span class="n" id="mwBck">DatabaseConnection</span><span class="o" id="mwBco">&</span><span class="w" id="mwBcs"> </span><span class="n" id="mwBcw">conn</span><span class="p" id="mwBc0">;</span> <span class="k" id="mwBc4">public</span><span class="o" id="mwBc8">:</span> <span class="w" id="mwBdA"> </span><span class="k" id="mwBdE">explicit</span><span class="w" id="mwBdI"> </span><span class="n" id="mwBdM">DatabaseService</span><span class="p" id="mwBdQ">(</span><span class="n" id="mwBdU">DatabaseConnection</span><span class="o" id="mwBdY">&</span><span class="w" id="mwBdc"> </span><span class="n" id="mwBdg">db</span><span class="p" id="mwBdk">)</span><span class="o" id="mwBdo">:</span> <span class="w" id="mwBds"> </span><span class="n" id="mwBdw">conn</span><span class="p" id="mwBd0">{</span><span class="n" id="mwBd4">db</span><span class="p" id="mwBd8">}</span><span class="w" id="mwBeA"> </span><span class="p" id="mwBeE">{}</span> <span class="w" id="mwBeI"> </span><span class="kt" id="mwBeM">void</span><span class="w" id="mwBeQ"> </span><span class="n" id="mwBeU">execute</span><span class="p" id="mwBeY">()</span><span class="w" id="mwBec"> </span><span class="p" id="mwBeg">{</span> <span class="w" id="mwBek"> </span><span class="n" id="mwBeo">conn</span><span class="p" id="mwBes">.</span><span class="n" id="mwBew">connect</span><span class="p" id="mwBe0">();</span> <span class="w" id="mwBe4"> </span><span class="n" id="mwBe8">std</span><span class="o" id="mwBfA">::</span><span class="n" id="mwBfE">println</span><span class="p" id="mwBfI">(</span><span class="s" id="mwBfM">"Executing database service..."</span><span class="p" id="mwBfQ">);</span> <span class="w" id="mwBfU"> </span><span class="p" id="mwBfY">}</span> <span class="p" id="mwBfc">};</span> <span class="kt" id="mwBfg">int</span><span class="w" id="mwBfk"> </span><span class="nf" id="mwBfo">main</span><span class="p" id="mwBfs">(</span><span class="kt" id="mwBfw">int</span><span class="w" id="mwBf0"> </span><span class="n" id="mwBf4">argc</span><span class="p" id="mwBf8">,</span><span class="w" id="mwBgA"> </span><span class="kt" id="mwBgE">char</span><span class="o" id="mwBgI">*</span><span class="w" id="mwBgM"> </span><span class="n" id="mwBgQ">argv</span><span class="p" id="mwBgU">[])</span><span class="w" id="mwBgY"> </span><span class="p" id="mwBgc">{</span> <span class="w" id="mwBgg"> </span><span class="n" id="mwBgk">DatabaseConnection</span><span class="w" id="mwBgo"> </span><span class="n" id="mwBgs">db</span><span class="p" id="mwBgw">;</span> <span class="w" id="mwBg0"> </span><span class="n" id="mwBg4">DatabaseService</span><span class="w" id="mwBg8"> </span><span class="n" id="mwBhA">sv</span><span class="p" id="mwBhE">(</span><span class="n" id="mwBhI">db</span><span class="p" id="mwBhM">);</span> <span class="w" id="mwBhQ"> </span> <span class="w" id="mwBhU"> </span><span class="n" id="mwBhY">sv</span><span class="p" id="mwBhc">.</span><span class="n" id="mwBhg">execute</span><span class="p" id="mwBhk">();</span> <span class="p" id="mwBho">}</span>This sample provides an example of interface injection.
<span id="mwBh4"></span><span class="k" id="mwBh8">import</span><span class="w" id="mwBiA"> </span><span class="n" id="mwBiE">std</span><span class="p" id="mwBiI">;</span> <span class="k" id="mwBiM">using</span><span class="w" id="mwBiQ"> </span><span class="n" id="mwBiU">std</span><span class="o" id="mwBiY">::</span><span class="n" id="mwBic">expected</span><span class="p" id="mwBig">;</span> <span class="k" id="mwBik">using</span><span class="w" id="mwBio"> </span><span class="n" id="mwBis">std</span><span class="o" id="mwBiw">::</span><span class="n" id="mwBi0">shared_ptr</span><span class="p" id="mwBi4">;</span> <span class="k" id="mwBi8">using</span><span class="w" id="mwBjA"> </span><span class="n" id="mwBjE">std</span><span class="o" id="mwBjI">::</span><span class="n" id="mwBjM">unexpected</span><span class="p" id="mwBjQ">;</span> <span class="k" id="mwBjU">class</span><span class="w" id="mwBjY"> </span><span class="nc" id="mwBjc">IConnection</span><span class="w" id="mwBjg"> </span><span class="p" id="mwBjk">{</span> <span class="k" id="mwBjo">public</span><span class="o" id="mwBjs">:</span> <span class="w" id="mwBjw"> </span><span class="k" id="mwBj0">enum</span><span class="w" id="mwBj4"> </span><span class="k" id="mwBj8">class</span><span class="w" id="mwBkA"> </span><span class="nc" id="mwBkE">Error</span><span class="w" id="mwBkI"> </span><span class="p" id="mwBkM">{</span> <span class="w" id="mwBkQ"> </span><span class="n" id="mwBkU">NO_CONNECTION</span><span class="p" id="mwBkY">,</span> <span class="w" id="mwBkc"> </span><span class="c1" id="mwBkg">// more errors here</span> <span class="w" id="mwBkk"> </span><span class="p" id="mwBko">};</span> <span class="w" id="mwBks"> </span><span class="k" id="mwBkw">virtual</span><span class="w" id="mwBk0"> </span><span class="kt" id="mwBk4">void</span><span class="w" id="mwBk8"> </span><span class="nf" id="mwBlA">connect</span><span class="p" id="mwBlE">()</span><span class="w" id="mwBlI"> </span><span class="o" id="mwBlM">=</span><span class="w" id="mwBlQ"> </span><span class="mi" id="mwBlU">0</span><span class="p" id="mwBlY">;</span> <span class="w" id="mwBlc"> </span><span class="k" id="mwBlg">virtual</span><span class="w" id="mwBlk"> </span><span class="o" id="mwBlo">~</span><span class="n" id="mwBls">IConnection</span><span class="p" id="mwBlw">()</span><span class="w" id="mwBl0"> </span><span class="o" id="mwBl4">=</span><span class="w" id="mwBl8"> </span><span class="k" id="mwBmA">default</span><span class="p" id="mwBmE">;</span> <span class="p" id="mwBmI">};</span> <span class="k" id="mwBmM">class</span><span class="w" id="mwBmQ"> </span><span class="nc" id="mwBmU">DatabaseConnection</span><span class="o" id="mwBmY">:</span><span class="w" id="mwBmc"> </span><span class="k" id="mwBmg">public</span><span class="w" id="mwBmk"> </span><span class="n" id="mwBmo">IConnection</span><span class="w" id="mwBms"> </span><span class="p" id="mwBmw">{</span> <span class="k" id="mwBm0">public</span><span class="o" id="mwBm4">:</span> <span class="w" id="mwBm8"> </span><span class="n" id="mwBnA">DatabaseConnection</span><span class="p" id="mwBnE">()</span><span class="w" id="mwBnI"> </span><span class="o" id="mwBnM">=</span><span class="w" id="mwBnQ"> </span><span class="k" id="mwBnU">default</span><span class="p" id="mwBnY">;</span> <span class="w" id="mwBnc"> </span><span class="kt" id="mwBng">void</span><span class="w" id="mwBnk"> </span><span class="nf" id="mwBno">connect</span><span class="p" id="mwBns">()</span><span class="w" id="mwBnw"> </span><span class="k" id="mwBn0">override</span><span class="w" id="mwBn4"> </span><span class="p" id="mwBn8">{</span> <span class="w" id="mwBoA"> </span><span class="n" id="mwBoE">std</span><span class="o" id="mwBoI">::</span><span class="n" id="mwBoM">println</span><span class="p" id="mwBoQ">(</span><span class="s" id="mwBoU">"Connecting to database..."</span><span class="p" id="mwBoY">);</span> <span class="w" id="mwBoc"> </span><span class="p" id="mwBog">}</span> <span class="p" id="mwBok">};</span> <span class="k" id="mwBoo">class</span><span class="w" id="mwBos"> </span><span class="nc" id="mwBow">DatabaseService</span><span class="w" id="mwBo0"> </span><span class="p" id="mwBo4">{</span> <span class="k" id="mwBo8">private</span><span class="o" id="mwBpA">:</span> <span class="w" id="mwBpE"> </span><span class="n" id="mwBpI">shared_ptr</span><span class="o" id="mwBpM"><</span><span class="n" id="mwBpQ">IConnection</span><span class="o" id="mwBpU">></span><span class="w" id="mwBpY"> </span><span class="n" id="mwBpc">conn</span><span class="p" id="mwBpg">;</span> <span class="k" id="mwBpk">public</span><span class="o" id="mwBpo">:</span> <span class="w" id="mwBps"> </span><span class="n" id="mwBpw">DatabaseService</span><span class="p" id="mwBp0">()</span><span class="w" id="mwBp4"> </span><span class="o" id="mwBp8">=</span><span class="w" id="mwBqA"> </span><span class="k" id="mwBqE">default</span><span class="p" id="mwBqI">;</span> <span class="w" id="mwBqM"> </span><span class="kt" id="mwBqQ">void</span><span class="w" id="mwBqU"> </span><span class="nf" id="mwBqY">setConnection</span><span class="p" id="mwBqc">(</span><span class="n" id="mwBqg">shared_ptr</span><span class="o" id="mwBqk"><</span><span class="n" id="mwBqo">IConnection</span><span class="o" id="mwBqs">></span><span class="w" id="mwBqw"> </span><span class="n" id="mwBq0">nextConn</span><span class="p" id="mwBq4">)</span><span class="w" id="mwBq8"> </span><span class="k" id="mwBrA">noexcept</span><span class="w" id="mwBrE"> </span><span class="p" id="mwBrI">{</span> <span class="w" id="mwBrM"> </span><span class="n" id="mwBrQ">conn</span><span class="w" id="mwBrU"> </span><span class="o" id="mwBrY">=</span><span class="w" id="mwBrc"> </span><span class="n" id="mwBrg">nextConn</span><span class="p" id="mwBrk">;</span> <span class="w" id="mwBro"> </span><span class="p" id="mwBrs">}</span> <span class="w" id="mwBrw"> </span><span class="n" id="mwBr0">expected</span><span class="o" id="mwBr4"><</span><span class="kt" id="mwBr8">void</span><span class="p" id="mwBsA">,</span><span class="w" id="mwBsE"> </span><span class="n" id="mwBsI">IConnection</span><span class="o" id="mwBsM">::</span><span class="n" id="mwBsQ">Error</span><span class="o" id="mwBsU">></span><span class="w" id="mwBsY"> </span><span class="n" id="mwBsc">execute</span><span class="p" id="mwBsg">()</span><span class="w" id="mwBsk"> </span><span class="p" id="mwBso">{</span> <span class="w" id="mwBss"> </span><span class="k" id="mwBsw">if</span><span class="w" id="mwBs0"> </span><span class="p" id="mwBs4">(</span><span class="n" id="mwBs8">conn</span><span class="p" id="mwBtA">)</span><span class="w" id="mwBtE"> </span><span class="p" id="mwBtI">{</span> <span class="w" id="mwBtM"> </span><span class="n" id="mwBtQ">conn</span><span class="o" id="mwBtU">-></span><span class="n" id="mwBtY">connect</span><span class="p" id="mwBtc">();</span> <span class="w" id="mwBtg"> </span><span class="n" id="mwBtk">std</span><span class="o" id="mwBto">::</span><span class="n" id="mwBts">println</span><span class="p" id="mwBtw">(</span><span class="s" id="mwBt0">"Executing database service..."</span><span class="p" id="mwBt4">);</span> <span class="w" id="mwBt8"> </span><span class="p" id="mwBuA">}</span><span class="w" id="mwBuE"> </span><span class="k" id="mwBuI">else</span><span class="w" id="mwBuM"> </span><span class="p" id="mwBuQ">{</span> <span class="w" id="mwBuU"> </span><span class="k" id="mwBuY">return</span><span class="w" id="mwBuc"> </span><span class="n" id="mwBug">unexpected</span><span class="p" id="mwBuk">(</span><span class="n" id="mwBuo">IConnection</span><span class="o" id="mwBus">::</span><span class="n" id="mwBuw">Error</span><span class="o" id="mwBu0">::</span><span class="n" id="mwBu4">NO_CONNECTION</span><span class="p" id="mwBu8">);</span> <span class="w" id="mwBvA"> </span><span class="p" id="mwBvE">}</span> <span class="w" id="mwBvI"> </span><span class="p" id="mwBvM">}</span> <span class="p" id="mwBvQ">};</span> <span class="kt" id="mwBvU">int</span><span class="w" id="mwBvY"> </span><span class="nf" id="mwBvc">main</span><span class="p" id="mwBvg">(</span><span class="kt" id="mwBvk">int</span><span class="w" id="mwBvo"> </span><span class="n" id="mwBvs">argc</span><span class="p" id="mwBvw">,</span><span class="w" id="mwBv0"> </span><span class="kt" id="mwBv4">char</span><span class="o" id="mwBv8">*</span><span class="w" id="mwBwA"> </span><span class="n" id="mwBwE">argv</span><span class="p" id="mwBwI">[])</span><span class="w" id="mwBwM"> </span><span class="p" id="mwBwQ">{</span> <span class="w" id="mwBwU"> </span><span class="n" id="mwBwY">shared_ptr</span><span class="o" id="mwBwc"><</span><span class="n" id="mwBwg">DatabaseConnection</span><span class="o" id="mwBwk">></span><span class="w" id="mwBwo"> </span><span class="n" id="mwBws">db</span><span class="w" id="mwBww"> </span><span class="o" id="mwBw0">=</span><span class="w" id="mwBw4"> </span><span class="n" id="mwBw8">std</span><span class="o" id="mwBxA">::</span><span class="n" id="mwBxE">make_shared</span><span class="o" id="mwBxI"><</span><span class="n" id="mwBxM">DatabaseConnection</span><span class="o" id="mwBxQ">></span><span class="p" id="mwBxU">();</span> <span class="w" id="mwBxY"> </span><span class="n" id="mwBxc">DatabaseService</span><span class="w" id="mwBxg"> </span><span class="n" id="mwBxk">sv</span><span class="p" id="mwBxo">;</span> <span class="w" id="mwBxs"> </span><span class="n" id="mwBxw">sv</span><span class="p" id="mwBx0">.</span><span class="n" id="mwBx4">setConnection</span><span class="p" id="mwBx8">(</span><span class="n" id="mwByA">db</span><span class="p" id="mwByE">);</span> <span class="w" id="mwByI"> </span><span class="n" id="mwByM">sv</span><span class="p" id="mwByQ">.</span><span class="n" id="mwByU">execute</span><span class="p" id="mwByY">();</span> <span class="p" id="mwByc">}</span>Historically, because C++ lacked reflection, libraries could not "see" constructor signatures or class member types, forcing the usage of manual dependency injection or metaprogramming libraries such as Boost.DI to manually map arguments to dependency injections. This is simplified greatly using C++26's function parameter reflection and annotations.
<span id="mwBz0"></span><span class="k" id="mwBz4">import</span><span class="w" id="mwBz8"> </span><span class="n" id="mwB0A">std</span><span class="p" id="mwB0E">;</span> <span class="k" id="mwB0I">using</span><span class="w" id="mwB0M"> </span><span class="n" id="mwB0Q">std</span><span class="o" id="mwB0U">::</span><span class="n" id="mwB0Y">string</span><span class="p" id="mwB0c">;</span> <span class="k" id="mwB0g">class</span><span class="w" id="mwB0k"> </span><span class="nc" id="mwB0o">IDatabase</span><span class="w" id="mwB0s"> </span><span class="p" id="mwB0w">{</span><span class="w" id="mwB00"> </span><span class="cm" id="mwB04">/* ... */</span><span class="w" id="mwB08"> </span><span class="p" id="mwB1A">};</span> <span class="k" id="mwB1E">class</span><span class="w" id="mwB1I"> </span><span class="nc" id="mwB1M">FastDatabase</span><span class="w" id="mwB1Q"> </span><span class="o" id="mwB1U">:</span><span class="w" id="mwB1Y"> </span><span class="k" id="mwB1c">public</span><span class="w" id="mwB1g"> </span><span class="n" id="mwB1k">IDatabase</span><span class="w" id="mwB1o"> </span><span class="p" id="mwB1s">{</span><span class="w" id="mwB1w"> </span><span class="cm" id="mwB10">/* ... */</span><span class="w" id="mwB14"> </span><span class="p" id="mwB18">};</span> <span class="k" id="mwB2A">class</span><span class="w" id="mwB2E"> </span><span class="nc" id="mwB2I">BasicDatabase</span><span class="w" id="mwB2M"> </span><span class="o" id="mwB2Q">:</span><span class="w" id="mwB2U"> </span><span class="k" id="mwB2Y">public</span><span class="w" id="mwB2c"> </span><span class="n" id="mwB2g">IDatabase</span><span class="w" id="mwB2k"> </span><span class="p" id="mwB2o">{</span><span class="w" id="mwB2s"> </span><span class="cm" id="mwB2w">/* ... */</span><span class="w" id="mwB20"> </span><span class="p" id="mwB24">};</span> <span class="k" id="mwB28">class</span><span class="w" id="mwB3A"> </span><span class="nc" id="mwB3E">Foo</span><span class="w" id="mwB3I"> </span><span class="p" id="mwB3M">{</span> <span class="k" id="mwB3Q">private</span><span class="o" id="mwB3U">:</span> <span class="w" id="mwB3Y"> </span><span class="c1" id="mwB3c">// ...</span> <span class="k" id="mwB3g">public</span><span class="o" id="mwB3k">:</span> <span class="w" id="mwB3o"> </span><span class="p" id="mwB3s">[[=</span><span class="nd" id="mwB3w">Inject</span><span class="p" id="mwB30">]]</span> <span class="w" id="mwB34"> </span><span class="n" id="mwB38">Foo</span><span class="p" id="mwB4A">(</span><span class="k" id="mwB4E">const</span><span class="w" id="mwB4I"> </span><span class="n" id="mwB4M">IDatabase</span><span class="o" id="mwB4Q">&</span><span class="w" id="mwB4U"> </span><span class="n" id="mwB4Y">primary</span><span class="p" id="mwB4c">,</span><span class="w" id="mwB4g"> </span><span class="k" id="mwB4k">const</span><span class="w" id="mwB4o"> </span><span class="n" id="mwB4s">IDatabase</span><span class="o" id="mwB4w">&</span><span class="w" id="mwB40"> </span><span class="n" id="mwB44">secondary</span><span class="p" id="mwB48">,</span><span class="w" id="mwB5A"> </span><span class="k" id="mwB5E">const</span><span class="w" id="mwB5I"> </span><span class="n" id="mwB5M">string</span><span class="o" id="mwB5Q">&</span><span class="w" id="mwB5U"> </span><span class="n" id="mwB5Y">s</span><span class="p" id="mwB5c">,</span><span class="w" id="mwB5g"> </span><span class="kt" id="mwB5k">int</span><span class="w" id="mwB5o"> </span><span class="n" id="mwB5s">i</span><span class="p" id="mwB5w">)</span><span class="w" id="mwB50"> </span><span class="p" id="mwB54">{</span> <span class="w" id="mwB58"> </span><span class="c1" id="mwB6A">// ...</span> <span class="w" id="mwB6E"> </span><span class="p" id="mwB6I">}</span> <span class="p" id="mwB6M">};</span> <span class="k" id="mwB6Q">class</span><span class="w" id="mwB6U"> </span><span class="nc" id="mwB6Y">Bar</span><span class="w" id="mwB6c"> </span><span class="p" id="mwB6g">{</span> <span class="k" id="mwB6k">private</span><span class="o" id="mwB6o">:</span> <span class="w" id="mwB6s"> </span><span class="c1" id="mwB6w">// ...</span> <span class="k" id="mwB60">public</span><span class="o" id="mwB64">:</span> <span class="w" id="mwB68"> </span><span class="p" id="mwB7A">[[=</span><span class="nd" id="mwB7E">Inject</span><span class="p" id="mwB7I">]]</span> <span class="w" id="mwB7M"> </span><span class="n" id="mwB7Q">Bar</span><span class="p" id="mwB7U">(</span><span class="k" id="mwB7Y">const</span><span class="w" id="mwB7c"> </span><span class="n" id="mwB7g">IDatabase</span><span class="o" id="mwB7k">&</span><span class="w" id="mwB7o"> </span><span class="n" id="mwB7s">primary</span><span class="p" id="mwB7w">,</span><span class="w" id="mwB70"> </span><span class="kt" id="mwB74">int</span><span class="w" id="mwB78"> </span><span class="n" id="mwB8A">i</span><span class="p" id="mwB8E">)</span><span class="w" id="mwB8I"> </span><span class="p" id="mwB8M">{</span> <span class="w" id="mwB8Q"> </span><span class="c1" id="mwB8U">// ...</span> <span class="w" id="mwB8Y"> </span><span class="p" id="mwB8c">}</span> <span class="p" id="mwB8g">};</span> <span class="kt" id="mwB8k">int</span><span class="w" id="mwB8o"> </span><span class="nf" id="mwB8s">main</span><span class="p" id="mwB8w">(</span><span class="kt" id="mwB80">int</span><span class="w" id="mwB84"> </span><span class="n" id="mwB88">argc</span><span class="p" id="mwB9A">,</span><span class="w" id="mwB9E"> </span><span class="kt" id="mwB9I">char</span><span class="o" id="mwB9M">*</span><span class="w" id="mwB9Q"> </span><span class="n" id="mwB9U">argv</span><span class="p" id="mwB9Y">[])</span><span class="w" id="mwB9c"> </span><span class="p" id="mwB9g">{</span> <span class="w" id="mwB9k"> </span><span class="n" id="mwB9o">Injector</span><span class="o" id="mwB9s"><</span><span class="n" id="mwB9w">IDatabase</span><span class="o" id="mwB90">></span><span class="w" id="mwB94"> </span><span class="n" id="mwB98">injector</span><span class="w" id="mwB-A"> </span><span class="o" id="mwB-E">=</span><span class="w" id="mwB-I"> </span><span class="n" id="mwB-M">Injector</span><span class="o" id="mwB-Q"><</span><span class="n" id="mwB-U">IDatabase</span><span class="o" id="mwB-Y">>::</span><span class="n" id="mwB-c">Builder</span><span class="p" id="mwB-g">()</span> <span class="w" id="mwB-k"> </span><span class="p" id="mwB-o">.</span><span class="n" id="mwB-s">addService</span><span class="p" id="mwB-w">(</span><span class="s" id="mwB-0">"primary"</span><span class="p" id="mwB-4">,</span><span class="w" id="mwB-8"> </span><span class="n" id="mwB_A">std</span><span class="o" id="mwB_E">::</span><span class="n" id="mwB_I">make_unique</span><span class="o" id="mwB_M"><</span><span class="n" id="mwB_Q">FastDatabase</span><span class="o" id="mwB_U">></span><span class="p" id="mwB_Y">())</span> <span class="w" id="mwB_c"> </span><span class="p" id="mwB_g">.</span><span class="n" id="mwB_k">addService</span><span class="p" id="mwB_o">(</span><span class="s" id="mwB_s">"secondary"</span><span class="p" id="mwB_w">,</span><span class="w" id="mwB_0"> </span><span class="n" id="mwB_4">std</span><span class="o" id="mwB_8">::</span><span class="n" id="mwCAA">make_unique</span><span class="o" id="mwCAE"><</span><span class="n" id="mwCAI">BasicDatabase</span><span class="o" id="mwCAM">></span><span class="p" id="mwCAQ">())</span> <span class="w" id="mwCAU"> </span><span class="p" id="mwCAY">.</span><span class="n" id="mwCAc">build</span><span class="p" id="mwCAg">();</span> <span class="w" id="mwCAk"> </span><span class="n" id="mwCAo">Foo</span><span class="w" id="mwCAs"> </span><span class="n" id="mwCAw">foo</span><span class="w" id="mwCA0"> </span><span class="o" id="mwCA4">=</span><span class="w" id="mwCA8"> </span><span class="n" id="mwCBA">injector</span><span class="p" id="mwCBE">.</span><span class="n" id="mwCBI">build</span><span class="o" id="mwCBM"><</span><span class="n" id="mwCBQ">Foo</span><span class="o" id="mwCBU">></span><span class="p" id="mwCBY">(</span><span class="s" id="mwCBc">"abc"</span><span class="p" id="mwCBg">,</span><span class="w" id="mwCBk"> </span><span class="mi" id="mwCBo">1</span><span class="p" id="mwCBs">);</span> <span class="w" id="mwCBw"> </span><span class="n" id="mwCB0">Bar</span><span class="w" id="mwCB4"> </span><span class="n" id="mwCB8">bar</span><span class="w" id="mwCCA"> </span><span class="o" id="mwCCE">=</span><span class="w" id="mwCCI"> </span><span class="n" id="mwCCM">injector</span><span class="p" id="mwCCQ">.</span><span class="n" id="mwCCU">build</span><span class="o" id="mwCCY"><</span><span class="n" id="mwCCc">Bar</span><span class="o" id="mwCCg">></span><span class="p" id="mwCCk">(</span><span class="mi" id="mwCCo">2</span><span class="p" id="mwCCs">);</span> <span class="p" id="mwCCw">}</span>C#
This sample provides an example of constructor injection in C#.
<span id="mwCDI"></span><span class="k" id="mwCDM">namespace</span><span class="w" id="mwCDQ"> </span><span class="nn" id="mwCDU">Wikipedia.Examples</span><span class="p" id="mwCDY">;</span> <span class="k" id="mwCDc">using</span><span class="w" id="mwCDg"> </span><span class="nn" id="mwCDk">System</span><span class="p" id="mwCDo">;</span> <span class="c1" id="mwCDs">// Our client will only know about this interface, not which specific gamepad it is using.</span> <span class="k" id="mwCDw">interface</span><span class="w" id="mwCD0"> </span><span class="n" id="mwCD4">IGamePadFunctionality</span><span class="w" id="mwCD8"> </span> <span class="p" id="mwCEA">{</span> <span class="w" id="mwCEE"> </span><span class="kt" id="mwCEI">string</span><span class="w" id="mwCEM"> </span><span class="nf" id="mwCEQ">GetGamePadName</span><span class="p" id="mwCEU">();</span> <span class="w" id="mwCEY"> </span><span class="k" id="mwCEc">void</span><span class="w" id="mwCEg"> </span><span class="nf" id="mwCEk">SetVibrationPower</span><span class="p" id="mwCEo">(</span><span class="kt" id="mwCEs">float</span><span class="w" id="mwCEw"> </span><span class="n" id="mwCE0">power</span><span class="p" id="mwCE4">);</span> <span class="p" id="mwCE8">}</span> <span class="c1" id="mwCFA">// The following services provide concrete implementations of the above interface.</span> <span class="k" id="mwCFE">class</span><span class="w" id="mwCFI"> </span><span class="nc" id="mwCFM">XboxGamePad</span><span class="w" id="mwCFQ"> </span><span class="p" id="mwCFU">:</span><span class="w" id="mwCFY"> </span><span class="n" id="mwCFc">IGamePadFunctionality</span><span class="w" id="mwCFg"> </span> <span class="p" id="mwCFk">{</span> <span class="w" id="mwCFo"> </span><span class="kt" id="mwCFs">float</span><span class="w" id="mwCFw"> </span><span class="n" id="mwCF0">vibrationPower</span><span class="w" id="mwCF4"> </span><span class="o" id="mwCF8">=</span><span class="w" id="mwCGA"> </span><span class="mf" id="mwCGE">1.0f</span><span class="p" id="mwCGI">;</span> <span class="w" id="mwCGM"> </span> <span class="w" id="mwCGQ"> </span><span class="k" id="mwCGU">public</span><span class="w" id="mwCGY"> </span><span class="kt" id="mwCGc">string</span><span class="w" id="mwCGg"> </span><span class="nf" id="mwCGk">GetGamePadName</span><span class="p" id="mwCGo">()</span><span class="w" id="mwCGs"> </span><span class="o" id="mwCGw">=></span><span class="w" id="mwCG0"> </span><span class="s" id="mwCG4">"Xbox controller"</span><span class="p" id="mwCG8">;</span> <span class="w" id="mwCHA"> </span> <span class="w" id="mwCHE"> </span><span class="k" id="mwCHI">public</span><span class="w" id="mwCHM"> </span><span class="k" id="mwCHQ">void</span><span class="w" id="mwCHU"> </span><span class="nf" id="mwCHY">SetVibrationPower</span><span class="p" id="mwCHc">(</span><span class="kt" id="mwCHg">float</span><span class="w" id="mwCHk"> </span><span class="n" id="mwCHo">power</span><span class="p" id="mwCHs">)</span><span class="w" id="mwCHw"> </span><span class="o" id="mwCH0">=></span> <span class="w" id="mwCH4"> </span><span class="k" id="mwCH8">this</span><span class="p" id="mwCIA">.</span><span class="n" id="mwCIE">vibrationPower</span><span class="w" id="mwCII"> </span><span class="o" id="mwCIM">=</span><span class="w" id="mwCIQ"> </span><span class="n" id="mwCIU">Math</span><span class="p" id="mwCIY">.</span><span class="n" id="mwCIc">Clamp</span><span class="p" id="mwCIg">(</span><span class="n" id="mwCIk">power</span><span class="p" id="mwCIo">,</span><span class="w" id="mwCIs"> </span><span class="mf" id="mwCIw">0.0f</span><span class="p" id="mwCI0">,</span><span class="w" id="mwCI4"> </span><span class="mf" id="mwCI8">1.0f</span><span class="p" id="mwCJA">);</span> <span class="p" id="mwCJE">}</span> <span class="k" id="mwCJI">class</span><span class="w" id="mwCJM"> </span><span class="nc" id="mwCJQ">PlayStationJoystick</span><span class="w" id="mwCJU"> </span><span class="p" id="mwCJY">:</span><span class="w" id="mwCJc"> </span><span class="n" id="mwCJg">IGamePadFunctionality</span><span class="w" id="mwCJk"> </span> <span class="p" id="mwCJo">{</span> <span class="w" id="mwCJs"> </span><span class="kt" id="mwCJw">float</span><span class="w" id="mwCJ0"> </span><span class="n" id="mwCJ4">vibratingPower</span><span class="w" id="mwCJ8"> </span><span class="o" id="mwCKA">=</span><span class="w" id="mwCKE"> </span><span class="mf" id="mwCKI">100.0f</span><span class="p" id="mwCKM">;</span> <span class="w" id="mwCKQ"> </span> <span class="w" id="mwCKU"> </span><span class="k" id="mwCKY">public</span><span class="w" id="mwCKc"> </span><span class="kt" id="mwCKg">string</span><span class="w" id="mwCKk"> </span><span class="nf" id="mwCKo">GetGamePadName</span><span class="p" id="mwCKs">()</span><span class="w" id="mwCKw"> </span><span class="o" id="mwCK0">=></span><span class="w" id="mwCK4"> </span><span class="s" id="mwCK8">"PlayStation controller"</span><span class="p" id="mwCLA">;</span> <span class="w" id="mwCLE"> </span> <span class="w" id="mwCLI"> </span><span class="k" id="mwCLM">public</span><span class="w" id="mwCLQ"> </span><span class="k" id="mwCLU">void</span><span class="w" id="mwCLY"> </span><span class="nf" id="mwCLc">SetVibrationPower</span><span class="p" id="mwCLg">(</span><span class="kt" id="mwCLk">float</span><span class="w" id="mwCLo"> </span><span class="n" id="mwCLs">power</span><span class="p" id="mwCLw">)</span><span class="w" id="mwCL0"> </span><span class="o" id="mwCL4">=></span> <span class="w" id="mwCL8"> </span><span class="k" id="mwCMA">this</span><span class="p" id="mwCME">.</span><span class="n" id="mwCMI">vibratingPower</span><span class="w" id="mwCMM"> </span><span class="o" id="mwCMQ">=</span><span class="w" id="mwCMU"> </span><span class="n" id="mwCMY">Math</span><span class="p" id="mwCMc">.</span><span class="n" id="mwCMg">Clamp</span><span class="p" id="mwCMk">(</span><span class="n" id="mwCMo">power</span><span class="w" id="mwCMs"> </span><span class="o" id="mwCMw">*</span><span class="w" id="mwCM0"> </span><span class="mf" id="mwCM4">100.0f</span><span class="p" id="mwCM8">,</span><span class="w" id="mwCNA"> </span><span class="mf" id="mwCNE">0.0f</span><span class="p" id="mwCNI">,</span><span class="w" id="mwCNM"> </span><span class="mf" id="mwCNQ">100.0f</span><span class="p" id="mwCNU">);</span> <span class="p" id="mwCNY">}</span> <span class="k" id="mwCNc">class</span><span class="w" id="mwCNg"> </span><span class="nc" id="mwCNk">SteamController</span><span class="w" id="mwCNo"> </span><span class="p" id="mwCNs">:</span><span class="w" id="mwCNw"> </span><span class="n" id="mwCN0">IGamePadFunctionality</span><span class="w" id="mwCN4"> </span> <span class="p" id="mwCN8">{</span> <span class="w" id="mwCOA"> </span><span class="kt" id="mwCOE">double</span><span class="w" id="mwCOI"> </span><span class="n" id="mwCOM">vibrating</span><span class="w" id="mwCOQ"> </span><span class="o" id="mwCOU">=</span><span class="w" id="mwCOY"> </span><span class="mf" id="mwCOc">1.0</span><span class="p" id="mwCOg">;</span> <span class="w" id="mwCOk"> </span> <span class="w" id="mwCOo"> </span><span class="k" id="mwCOs">public</span><span class="w" id="mwCOw"> </span><span class="kt" id="mwCO0">string</span><span class="w" id="mwCO4"> </span><span class="nf" id="mwCO8">GetGamePadName</span><span class="p" id="mwCPA">()</span><span class="w" id="mwCPE"> </span><span class="o" id="mwCPI">=></span><span class="w" id="mwCPM"> </span><span class="s" id="mwCPQ">"Steam controller"</span><span class="p" id="mwCPU">;</span> <span class="w" id="mwCPY"> </span> <span class="w" id="mwCPc"> </span><span class="k" id="mwCPg">public</span><span class="w" id="mwCPk"> </span><span class="k" id="mwCPo">void</span><span class="w" id="mwCPs"> </span><span class="nf" id="mwCPw">SetVibrationPower</span><span class="p" id="mwCP0">(</span><span class="kt" id="mwCP4">float</span><span class="w" id="mwCP8"> </span><span class="n" id="mwCQA">power</span><span class="p" id="mwCQE">)</span><span class="w" id="mwCQI"> </span><span class="o" id="mwCQM">=></span> <span class="w" id="mwCQQ"> </span><span class="k" id="mwCQU">this</span><span class="p" id="mwCQY">.</span><span class="n" id="mwCQc">vibrating</span><span class="w" id="mwCQg"> </span><span class="o" id="mwCQk">=</span><span class="w" id="mwCQo"> </span><span class="n" id="mwCQs">Convert</span><span class="p" id="mwCQw">.</span><span class="n" id="mwCQ0">ToDouble</span><span class="p" id="mwCQ4">(</span><span class="n" id="mwCQ8">Math</span><span class="p" id="mwCRA">.</span><span class="n" id="mwCRE">Clamp</span><span class="p" id="mwCRI">(</span><span class="n" id="mwCRM">power</span><span class="p" id="mwCRQ">,</span><span class="w" id="mwCRU"> </span><span class="mf" id="mwCRY">0.0f</span><span class="p" id="mwCRc">,</span><span class="w" id="mwCRg"> </span><span class="mf" id="mwCRk">1.0f</span><span class="p" id="mwCRo">));</span> <span class="p" id="mwCRs">}</span> <span class="c1" id="mwCRw">// This class is the client which receives a service.</span> <span class="k" id="mwCR0">class</span><span class="w" id="mwCR4"> </span><span class="nc" id="mwCR8">GamePad</span> <span class="p" id="mwCSA">{</span> <span class="w" id="mwCSE"> </span><span class="n" id="mwCSI">IGamePadFunctionality</span><span class="w" id="mwCSM"> </span><span class="n" id="mwCSQ">gamePadFunctionality</span><span class="p" id="mwCSU">;</span> <span class="w" id="mwCSY"> </span><span class="c1" id="mwCSc">// The service is injected through the constructor and stored in the above field.</span> <span class="w" id="mwCSg"> </span><span class="k" id="mwCSk">public</span><span class="w" id="mwCSo"> </span><span class="nf" id="mwCSs">GamePad</span><span class="p" id="mwCSw">(</span><span class="n" id="mwCS0">IGamePadFunctionality</span><span class="w" id="mwCS4"> </span><span class="n" id="mwCS8">gamePadFunctionality</span><span class="p" id="mwCTA">)</span><span class="w" id="mwCTE"> </span><span class="o" id="mwCTI">=></span> <span class="w" id="mwCTM"> </span><span class="k" id="mwCTQ">this</span><span class="p" id="mwCTU">.</span><span class="n" id="mwCTY">gamePadFunctionality</span><span class="w" id="mwCTc"> </span><span class="o" id="mwCTg">=</span><span class="w" id="mwCTk"> </span><span class="n" id="mwCTo">gamePadFunctionality</span><span class="p" id="mwCTs">;</span> <span class="w" id="mwCTw"> </span><span class="k" id="mwCT0">public</span><span class="w" id="mwCT4"> </span><span class="k" id="mwCT8">void</span><span class="w" id="mwCUA"> </span><span class="nf" id="mwCUE">Showcase</span><span class="p" id="mwCUI">()</span><span class="w" id="mwCUM"> </span> <span class="w" id="mwCUQ"> </span><span class="p" id="mwCUU">{</span> <span class="w" id="mwCUY"> </span><span class="c1" id="mwCUc">// The injected service is used.</span> <span class="w" id="mwCUg"> </span><span class="kt" id="mwCUk">string</span><span class="w" id="mwCUo"> </span><span class="n" id="mwCUs">gamePadName</span><span class="w" id="mwCUw"> </span><span class="o" id="mwCU0">=</span><span class="w" id="mwCU4"> </span><span class="k" id="mwCU8">this</span><span class="p" id="mwCVA">.</span><span class="n" id="mwCVE">gamePadFunctionality</span><span class="p" id="mwCVI">.</span><span class="n" id="mwCVM">GetGamePadName</span><span class="p" id="mwCVQ">();</span> <span class="w" id="mwCVU"> </span><span class="kt" id="mwCVY">string</span><span class="w" id="mwCVc"> </span><span class="n" id="mwCVg">message</span><span class="w" id="mwCVk"> </span><span class="o" id="mwCVo">=</span><span class="w" id="mwCVs"> </span><span class="s" id="mwCVw">$"We're using the {gamePadName} right now, do you want to change the vibrating power?"</span><span class="p" id="mwCV0">;</span> <span class="w" id="mwCV4"> </span><span class="n" id="mwCV8">Console</span><span class="p" id="mwCWA">.</span><span class="n" id="mwCWE">WriteLine</span><span class="p" id="mwCWI">(</span><span class="n" id="mwCWM">message</span><span class="p" id="mwCWQ">);</span> <span class="w" id="mwCWU"> </span><span class="p" id="mwCWY">}</span> <span class="p" id="mwCWc">}</span> <span class="k" id="mwCWg">class</span><span class="w" id="mwCWk"> </span><span class="nc" id="mwCWo">Program</span> <span class="p" id="mwCWs">{</span> <span class="w" id="mwCWw"> </span><span class="k" id="mwCW0">static</span><span class="w" id="mwCW4"> </span><span class="k" id="mwCW8">void</span><span class="w" id="mwCXA"> </span><span class="nf" id="mwCXE">Main</span><span class="p" id="mwCXI">(</span><span class="kt" id="mwCXM">string</span><span class="p" id="mwCXQ">[]</span><span class="w" id="mwCXU"> </span><span class="n" id="mwCXY">args</span><span class="p" id="mwCXc">)</span><span class="w" id="mwCXg"> </span> <span class="w" id="mwCXk"> </span><span class="p" id="mwCXo">{</span> <span class="w" id="mwCXs"> </span><span class="n" id="mwCXw">SteamController</span><span class="w" id="mwCX0"> </span><span class="n" id="mwCX4">steamController</span><span class="w" id="mwCX8"> </span><span class="o" id="mwCYA">=</span><span class="w" id="mwCYE"> </span><span class="k" id="mwCYI">new</span><span class="p" id="mwCYM">();</span> <span class="w" id="mwCYQ"> </span> <span class="w" id="mwCYU"> </span><span class="c1" id="mwCYY">// We could have also passed in an XboxController, PlayStationJoystick, etc.</span> <span class="w" id="mwCYc"> </span><span class="c1" id="mwCYg">// The gamepad doesn't know what it's using and doesn't need to.</span> <span class="w" id="mwCYk"> </span><span class="n" id="mwCYo">GamePad</span><span class="w" id="mwCYs"> </span><span class="n" id="mwCYw">gamepad</span><span class="w" id="mwCY0"> </span><span class="o" id="mwCY4">=</span><span class="w" id="mwCY8"> </span><span class="k" id="mwCZA">new</span><span class="p" id="mwCZE">(</span><span class="n" id="mwCZI">steamController</span><span class="p" id="mwCZM">);</span> <span class="w" id="mwCZQ"> </span> <span class="w" id="mwCZU"> </span><span class="n" id="mwCZY">gamepad</span><span class="p" id="mwCZc">.</span><span class="n" id="mwCZg">Showcase</span><span class="p" id="mwCZk">();</span> <span class="w" id="mwCZo"> </span><span class="p" id="mwCZs">}</span> <span class="p" id="mwCZw">}</span>Go
Go does not support classes and usually dependency injection is either abstracted by a dedicated library that utilizes reflection or generics (the latter being supported since Go 1.18). A simpler example without using dependency injection libraries is illustrated by the following example of an MVC web application.
First, pass the necessary dependencies to a router and then from the router to the controllers:
<span id="mwCa0"></span><span class="kn" id="mwCa4">package</span><span class="w" id="mwCa8"> </span><span class="nx" id="mwCbA">router</span> <span class="kn" id="mwCbE">import</span><span class="w" id="mwCbI"> </span><span class="p" id="mwCbM">(</span> <span class="w" id="mwCbQ"> </span><span class="s" id="mwCbU">"database/sql"</span> <span class="w" id="mwCbY"> </span><span class="s" id="mwCbc">"net/http"</span> <span class="w" id="mwCbg"> </span><span class="s" id="mwCbk">"example/controllers/users"</span> <span class="w" id="mwCbo"> </span><span class="s" id="mwCbs">"github.com/go-chi/chi/v5"</span> <span class="w" id="mwCbw"> </span><span class="s" id="mwCb0">"github.com/go-chi/chi/v5/middleware"</span> <span class="w" id="mwCb4"> </span><span class="s" id="mwCb8">"github.com/redis/go-redis/v9"</span> <span class="w" id="mwCcA"> </span><span class="s" id="mwCcE">"github.com/rs/zerolog"</span> <span class="p" id="mwCcI">)</span> <span class="kd" id="mwCcM">type</span><span class="w" id="mwCcQ"> </span><span class="nx" id="mwCcU">RoutingHandler</span><span class="w" id="mwCcY"> </span><span class="kd" id="mwCcc">struct</span><span class="w" id="mwCcg"> </span><span class="p" id="mwCck">{</span> <span class="w" id="mwCco"> </span><span class="c1" id="mwCcs">// passing the values by pointer further down the call stack</span> <span class="w" id="mwCcw"> </span><span class="c1" id="mwCc0">// means we won't create a new copy, saving memory</span> <span class="w" id="mwCc4"> </span><span class="nx" id="mwCc8">log</span><span class="w" id="mwCdA"> </span><span class="o" id="mwCdE">*</span><span class="nx" id="mwCdI">zerolog</span><span class="p" id="mwCdM">.</span><span class="nx" id="mwCdQ">Logger</span> <span class="w" id="mwCdU"> </span><span class="nx" id="mwCdY">db</span><span class="w" id="mwCdc"> </span><span class="o" id="mwCdg">*</span><span class="nx" id="mwCdk">sql</span><span class="p" id="mwCdo">.</span><span class="nx" id="mwCds">DB</span> <span class="w" id="mwCdw"> </span><span class="nx" id="mwCd0">cache</span><span class="w" id="mwCd4"> </span><span class="o" id="mwCd8">*</span><span class="nx" id="mwCeA">redis</span><span class="p" id="mwCeE">.</span><span class="nx" id="mwCeI">Client</span> <span class="w" id="mwCeM"> </span><span class="nx" id="mwCeQ">router</span><span class="w" id="mwCeU"> </span><span class="nx" id="mwCeY">chi</span><span class="p" id="mwCec">.</span><span class="nx" id="mwCeg">Router</span> <span class="p" id="mwCek">}</span> <span class="c1" id="mwCeo">// connection, logger and cache initialized usually in the main function</span> <span class="kd" id="mwCes">func</span><span class="w" id="mwCew"> </span><span class="nx" id="mwCe0">NewRouter</span><span class="p" id="mwCe4">(</span> <span class="w" id="mwCe8"> </span><span class="nx" id="mwCfA">log</span><span class="w" id="mwCfE"> </span><span class="o" id="mwCfI">*</span><span class="nx" id="mwCfM">zerolog</span><span class="p" id="mwCfQ">.</span><span class="nx" id="mwCfU">Logger</span><span class="p" id="mwCfY">,</span> <span class="w" id="mwCfc"> </span><span class="nx" id="mwCfg">db</span><span class="w" id="mwCfk"> </span><span class="o" id="mwCfo">*</span><span class="nx" id="mwCfs">sql</span><span class="p" id="mwCfw">.</span><span class="nx" id="mwCf0">DB</span><span class="p" id="mwCf4">,</span> <span class="w" id="mwCf8"> </span><span class="nx" id="mwCgA">cache</span><span class="w" id="mwCgE"> </span><span class="o" id="mwCgI">*</span><span class="nx" id="mwCgM">redis</span><span class="p" id="mwCgQ">.</span><span class="nx" id="mwCgU">Client</span><span class="p" id="mwCgY">,</span> <span class="p" id="mwCgc">)</span><span class="w" id="mwCgg"> </span><span class="p" id="mwCgk">(</span><span class="nx" id="mwCgo">r</span><span class="w" id="mwCgs"> </span><span class="o" id="mwCgw">*</span><span class="nx" id="mwCg0">RoutingHandler</span><span class="p" id="mwCg4">)</span><span class="w" id="mwCg8"> </span><span class="p" id="mwChA">{</span> <span class="w" id="mwChE"> </span><span class="nx" id="mwChI">rtr</span><span class="w" id="mwChM"> </span><span class="o" id="mwChQ">:=</span><span class="w" id="mwChU"> </span><span class="nx" id="mwChY">chi</span><span class="p" id="mwChc">.</span><span class="nx" id="mwChg">NewRouter</span><span class="p" id="mwChk">()</span> <span class="w" id="mwCho"> </span><span class="k" id="mwChs">return</span><span class="w" id="mwChw"> </span><span class="o" id="mwCh0">&</span><span class="nx" id="mwCh4">RoutingHandler</span><span class="p" id="mwCh8">{</span> <span class="w" id="mwCiA"> </span><span class="nx" id="mwCiE">log</span><span class="p" id="mwCiI">:</span><span class="w" id="mwCiM"> </span><span class="nx" id="mwCiQ">log</span><span class="p" id="mwCiU">,</span> <span class="w" id="mwCiY"> </span><span class="nx" id="mwCic">db</span><span class="p" id="mwCig">:</span><span class="w" id="mwCik"> </span><span class="nx" id="mwCio">db</span><span class="p" id="mwCis">,</span> <span class="w" id="mwCiw"> </span><span class="nx" id="mwCi0">cache</span><span class="p" id="mwCi4">:</span><span class="w" id="mwCi8"> </span><span class="nx" id="mwCjA">cache</span><span class="p" id="mwCjE">,</span> <span class="w" id="mwCjI"> </span><span class="nx" id="mwCjM">router</span><span class="p" id="mwCjQ">:</span><span class="w" id="mwCjU"> </span><span class="nx" id="mwCjY">rtr</span><span class="p" id="mwCjc">,</span> <span class="w" id="mwCjg"> </span><span class="p" id="mwCjk">}</span> <span class="p" id="mwCjo">}</span> <span class="kd" id="mwCjs">func</span><span class="w" id="mwCjw"> </span><span class="p" id="mwCj0">(</span><span class="nx" id="mwCj4">r</span><span class="w" id="mwCj8"> </span><span class="o" id="mwCkA">*</span><span class="nx" id="mwCkE">RoutingHandler</span><span class="p" id="mwCkI">)</span><span class="w" id="mwCkM"> </span><span class="nx" id="mwCkQ">SetupUsersRoutes</span><span class="p" id="mwCkU">()</span><span class="w" id="mwCkY"> </span><span class="p" id="mwCkc">{</span> <span class="w" id="mwCkg"> </span><span class="nx" id="mwCkk">uc</span><span class="w" id="mwCko"> </span><span class="o" id="mwCks">:=</span><span class="w" id="mwCkw"> </span><span class="nx" id="mwCk0">users</span><span class="p" id="mwCk4">.</span><span class="nx" id="mwCk8">NewController</span><span class="p" id="mwClA">(</span><span class="nx" id="mwClE">r</span><span class="p" id="mwClI">.</span><span class="nx" id="mwClM">log</span><span class="p" id="mwClQ">,</span><span class="w" id="mwClU"> </span><span class="nx" id="mwClY">r</span><span class="p" id="mwClc">.</span><span class="nx" id="mwClg">db</span><span class="p" id="mwClk">,</span><span class="w" id="mwClo"> </span><span class="nx" id="mwCls">r</span><span class="p" id="mwClw">.</span><span class="nx" id="mwCl0">cache</span><span class="p" id="mwCl4">)</span> <span class="w" id="mwCl8"> </span><span class="nx" id="mwCmA">r</span><span class="p" id="mwCmE">.</span><span class="nx" id="mwCmI">router</span><span class="p" id="mwCmM">.</span><span class="nx" id="mwCmQ">Get</span><span class="p" id="mwCmU">(</span><span class="s" id="mwCmY">"/users/:name"</span><span class="p" id="mwCmc">,</span><span class="w" id="mwCmg"> </span><span class="kd" id="mwCmk">func</span><span class="p" id="mwCmo">(</span><span class="nx" id="mwCms">w</span><span class="w" id="mwCmw"> </span><span class="nx" id="mwCm0">http</span><span class="p" id="mwCm4">.</span><span class="nx" id="mwCm8">ResponseWriter</span><span class="p" id="mwCnA">,</span><span class="w" id="mwCnE"> </span><span class="nx" id="mwCnI">r</span><span class="w" id="mwCnM"> </span><span class="o" id="mwCnQ">*</span><span class="nx" id="mwCnU">http</span><span class="p" id="mwCnY">.</span><span class="nx" id="mwCnc">Request</span><span class="p" id="mwCng">)</span><span class="w" id="mwCnk"> </span><span class="p" id="mwCno">{</span> <span class="w" id="mwCns"> </span><span class="nx" id="mwCnw">uc</span><span class="p" id="mwCn0">.</span><span class="nx" id="mwCn4">Get</span><span class="p" id="mwCn8">(</span><span class="nx" id="mwCoA">w</span><span class="p" id="mwCoE">,</span><span class="w" id="mwCoI"> </span><span class="nx" id="mwCoM">r</span><span class="p" id="mwCoQ">)</span> <span class="w" id="mwCoU"> </span><span class="p" id="mwCoY">})</span> <span class="p" id="mwCoc">}</span>Then, the private fields of the struct can be accessed in any method that is its pointer receiver, without violating encapsulation.
<span id="mwCo0"></span><span class="kn" id="mwCo4">package</span><span class="w" id="mwCo8"> </span><span class="nx" id="mwCpA">users</span> <span class="kn" id="mwCpE">import</span><span class="w" id="mwCpI"> </span><span class="p" id="mwCpM">(</span> <span class="w" id="mwCpQ"> </span><span class="s" id="mwCpU">"database/sql"</span> <span class="w" id="mwCpY"> </span><span class="s" id="mwCpc">"net/http"</span> <span class="w" id="mwCpg"> </span><span class="s" id="mwCpk">"example/models"</span> <span class="w" id="mwCpo"> </span><span class="s" id="mwCps">"github.com/go-chi/chi/v5"</span> <span class="w" id="mwCpw"> </span><span class="s" id="mwCp0">"github.com/redis/go-redis/v9"</span> <span class="w" id="mwCp4"> </span><span class="s" id="mwCp8">"github.com/rs/zerolog"</span> <span class="p" id="mwCqA">)</span> <span class="kd" id="mwCqE">type</span><span class="w" id="mwCqI"> </span><span class="nx" id="mwCqM">Controller</span><span class="w" id="mwCqQ"> </span><span class="kd" id="mwCqU">struct</span><span class="w" id="mwCqY"> </span><span class="p" id="mwCqc">{</span> <span class="w" id="mwCqg"> </span><span class="nx" id="mwCqk">log</span><span class="w" id="mwCqo"> </span><span class="o" id="mwCqs">*</span><span class="nx" id="mwCqw">zerolog</span><span class="p" id="mwCq0">.</span><span class="nx" id="mwCq4">Logger</span> <span class="w" id="mwCq8"> </span><span class="nx" id="mwCrA">storage</span><span class="w" id="mwCrE"> </span><span class="nx" id="mwCrI">models</span><span class="p" id="mwCrM">.</span><span class="nx" id="mwCrQ">UserStorage</span> <span class="w" id="mwCrU"> </span><span class="nx" id="mwCrY">cache</span><span class="w" id="mwCrc"> </span><span class="o" id="mwCrg">*</span><span class="nx" id="mwCrk">redis</span><span class="p" id="mwCro">.</span><span class="nx" id="mwCrs">Client</span> <span class="p" id="mwCrw">}</span> <span class="kd" id="mwCr0">func</span><span class="w" id="mwCr4"> </span><span class="nx" id="mwCr8">NewController</span><span class="p" id="mwCsA">(</span><span class="nx" id="mwCsE">log</span><span class="w" id="mwCsI"> </span><span class="o" id="mwCsM">*</span><span class="nx" id="mwCsQ">zerolog</span><span class="p" id="mwCsU">.</span><span class="nx" id="mwCsY">Logger</span><span class="p" id="mwCsc">,</span><span class="w" id="mwCsg"> </span><span class="nx" id="mwCsk">db</span><span class="w" id="mwCso"> </span><span class="o" id="mwCss">*</span><span class="nx" id="mwCsw">sql</span><span class="p" id="mwCs0">.</span><span class="nx" id="mwCs4">DB</span><span class="p" id="mwCs8">,</span><span class="w" id="mwCtA"> </span><span class="nx" id="mwCtE">cache</span><span class="w" id="mwCtI"> </span><span class="o" id="mwCtM">*</span><span class="nx" id="mwCtQ">redis</span><span class="p" id="mwCtU">.</span><span class="nx" id="mwCtY">Client</span><span class="p" id="mwCtc">)</span><span class="w" id="mwCtg"> </span><span class="o" id="mwCtk">*</span><span class="nx" id="mwCto">Controller</span><span class="w" id="mwCts"> </span><span class="p" id="mwCtw">{</span> <span class="w" id="mwCt0"> </span><span class="k" id="mwCt4">return</span><span class="w" id="mwCt8"> </span><span class="o" id="mwCuA">&</span><span class="nx" id="mwCuE">Controller</span><span class="p" id="mwCuI">{</span> <span class="w" id="mwCuM"> </span><span class="nx" id="mwCuQ">log</span><span class="p" id="mwCuU">:</span><span class="w" id="mwCuY"> </span><span class="nx" id="mwCuc">log</span><span class="p" id="mwCug">,</span> <span class="w" id="mwCuk"> </span><span class="nx" id="mwCuo">storage</span><span class="p" id="mwCus">:</span><span class="w" id="mwCuw"> </span><span class="nx" id="mwCu0">models</span><span class="p" id="mwCu4">.</span><span class="nx" id="mwCu8">NewUserStorage</span><span class="p" id="mwCvA">(</span><span class="nx" id="mwCvE">db</span><span class="p" id="mwCvI">),</span> <span class="w" id="mwCvM"> </span><span class="nx" id="mwCvQ">cache</span><span class="p" id="mwCvU">:</span><span class="w" id="mwCvY"> </span><span class="nx" id="mwCvc">cache</span><span class="p" id="mwCvg">,</span> <span class="w" id="mwCvk"> </span><span class="p" id="mwCvo">}</span> <span class="p" id="mwCvs">}</span> <span class="kd" id="mwCvw">func</span><span class="w" id="mwCv0"> </span><span class="p" id="mwCv4">(</span><span class="nx" id="mwCv8">uc</span><span class="w" id="mwCwA"> </span><span class="o" id="mwCwE">*</span><span class="nx" id="mwCwI">Controller</span><span class="p" id="mwCwM">)</span><span class="w" id="mwCwQ"> </span><span class="nx" id="mwCwU">Get</span><span class="p" id="mwCwY">(</span><span class="nx" id="mwCwc">w</span><span class="w" id="mwCwg"> </span><span class="nx" id="mwCwk">http</span><span class="p" id="mwCwo">.</span><span class="nx" id="mwCws">ResponseWriter</span><span class="p" id="mwCww">,</span><span class="w" id="mwCw0"> </span><span class="nx" id="mwCw4">r</span><span class="w" id="mwCw8"> </span><span class="o" id="mwCxA">*</span><span class="nx" id="mwCxE">http</span><span class="p" id="mwCxI">.</span><span class="nx" id="mwCxM">Request</span><span class="p" id="mwCxQ">)</span><span class="w" id="mwCxU"> </span><span class="p" id="mwCxY">{</span> <span class="w" id="mwCxc"> </span><span class="c1" id="mwCxg">// note that we can also wrap logging in a middleware, this is for demonstration purposes</span> <span class="w" id="mwCxk"> </span><span class="nx" id="mwCxo">uc</span><span class="p" id="mwCxs">.</span><span class="nx" id="mwCxw">log</span><span class="p" id="mwCx0">.</span><span class="nx" id="mwCx4">Info</span><span class="p" id="mwCx8">().</span><span class="nx" id="mwCyA">Msg</span><span class="p" id="mwCyE">(</span><span class="s" id="mwCyI">"Getting user"</span><span class="p" id="mwCyM">)</span> <span class="w" id="mwCyQ"> </span><span class="nx" id="mwCyU">userParam</span><span class="w" id="mwCyY"> </span><span class="o" id="mwCyc">:=</span><span class="w" id="mwCyg"> </span><span class="nx" id="mwCyk">chi</span><span class="p" id="mwCyo">.</span><span class="nx" id="mwCys">URLParam</span><span class="p" id="mwCyw">(</span><span class="nx" id="mwCy0">r</span><span class="p" id="mwCy4">,</span><span class="w" id="mwCy8"> </span><span class="s" id="mwCzA">"name"</span><span class="p" id="mwCzE">)</span> <span class="w" id="mwCzI"> </span><span class="kd" id="mwCzM">var</span><span class="w" id="mwCzQ"> </span><span class="nx" id="mwCzU">user</span><span class="w" id="mwCzY"> </span><span class="o" id="mwCzc">*</span><span class="nx" id="mwCzg">models</span><span class="p" id="mwCzk">.</span><span class="nx" id="mwCzo">User</span> <span class="w" id="mwCzs"> </span><span class="c1" id="mwCzw">// get the user from the cache</span> <span class="w" id="mwCz0"> </span><span class="nx" id="mwCz4">err</span><span class="w" id="mwCz8"> </span><span class="o" id="mwC0A">:=</span><span class="w" id="mwC0E"> </span><span class="nx" id="mwC0I">uc</span><span class="p" id="mwC0M">.</span><span class="nx" id="mwC0Q">cache</span><span class="p" id="mwC0U">.</span><span class="nx" id="mwC0Y">Get</span><span class="p" id="mwC0c">(</span><span class="nx" id="mwC0g">r</span><span class="p" id="mwC0k">.</span><span class="nx" id="mwC0o">Context</span><span class="p" id="mwC0s">(),</span><span class="w" id="mwC0w"> </span><span class="nx" id="mwC00">userParam</span><span class="p" id="mwC04">).</span><span class="nx" id="mwC08">Scan</span><span class="p" id="mwC1A">(</span><span class="o" id="mwC1E">&</span><span class="nx" id="mwC1I">user</span><span class="p" id="mwC1M">)</span> <span class="w" id="mwC1Q"> </span><span class="k" id="mwC1U">if</span><span class="w" id="mwC1Y"> </span><span class="nx" id="mwC1c">err</span><span class="w" id="mwC1g"> </span><span class="o" id="mwC1k">!=</span><span class="w" id="mwC1o"> </span><span class="kc" id="mwC1s">nil</span><span class="w" id="mwC1w"> </span><span class="p" id="mwC10">{</span> <span class="w" id="mwC14"> </span><span class="nx" id="mwC18">uc</span><span class="p" id="mwC2A">.</span><span class="nx" id="mwC2E">log</span><span class="p" id="mwC2I">.</span><span class="nx" id="mwC2M">Error</span><span class="p" id="mwC2Q">().</span><span class="nx" id="mwC2U">Err</span><span class="p" id="mwC2Y">(</span><span class="nx" id="mwC2c">err</span><span class="p" id="mwC2g">).</span><span class="nx" id="mwC2k">Msg</span><span class="p" id="mwC2o">(</span><span class="s" id="mwC2s">"Error getting user from cache. Retrieving from SQL storage"</span><span class="p" id="mwC2w">)</span> <span class="w" id="mwC20"> </span><span class="p" id="mwC24">}</span> <span class="w" id="mwC28"> </span><span class="nx" id="mwC3A">user</span><span class="p" id="mwC3E">,</span><span class="w" id="mwC3I"> </span><span class="nx" id="mwC3M">err</span><span class="w" id="mwC3Q"> </span><span class="o" id="mwC3U">=</span><span class="w" id="mwC3Y"> </span><span class="nx" id="mwC3c">uc</span><span class="p" id="mwC3g">.</span><span class="nx" id="mwC3k">storage</span><span class="p" id="mwC3o">.</span><span class="nx" id="mwC3s">Get</span><span class="p" id="mwC3w">(</span><span class="nx" id="mwC30">r</span><span class="p" id="mwC34">.</span><span class="nx" id="mwC38">Context</span><span class="p" id="mwC4A">(),</span><span class="w" id="mwC4E"> </span><span class="s" id="mwC4I">"johndoe"</span><span class="p" id="mwC4M">)</span> <span class="w" id="mwC4Q"> </span><span class="k" id="mwC4U">if</span><span class="w" id="mwC4Y"> </span><span class="nx" id="mwC4c">err</span><span class="w" id="mwC4g"> </span><span class="o" id="mwC4k">!=</span><span class="w" id="mwC4o"> </span><span class="kc" id="mwC4s">nil</span><span class="w" id="mwC4w"> </span><span class="p" id="mwC40">{</span> <span class="w" id="mwC44"> </span><span class="nx" id="mwC48">uc</span><span class="p" id="mwC5A">.</span><span class="nx" id="mwC5E">log</span><span class="p" id="mwC5I">.</span><span class="nx" id="mwC5M">Error</span><span class="p" id="mwC5Q">().</span><span class="nx" id="mwC5U">Err</span><span class="p" id="mwC5Y">(</span><span class="nx" id="mwC5c">err</span><span class="p" id="mwC5g">).</span><span class="nx" id="mwC5k">Msg</span><span class="p" id="mwC5o">(</span><span class="s" id="mwC5s">"Error getting user from SQL storage"</span><span class="p" id="mwC5w">)</span> <span class="w" id="mwC50"> </span><span class="nx" id="mwC54">http</span><span class="p" id="mwC58">.</span><span class="nx" id="mwC6A">Error</span><span class="p" id="mwC6E">(</span><span class="nx" id="mwC6I">w</span><span class="p" id="mwC6M">,</span><span class="w" id="mwC6Q"> </span><span class="s" id="mwC6U">"Internal server error"</span><span class="p" id="mwC6Y">,</span><span class="w" id="mwC6c"> </span><span class="nx" id="mwC6g">http</span><span class="p" id="mwC6k">.</span><span class="nx" id="mwC6o">StatusInternalServerError</span><span class="p" id="mwC6s">)</span> <span class="w" id="mwC6w"> </span><span class="k" id="mwC60">return</span> <span class="w" id="mwC64"> </span><span class="p" id="mwC68">}</span> <span class="p" id="mwC7A">}</span>Finally, the database connection initialized in the main function can be used at the data access layer:
<span id="mwC7Q"></span><span class="kn" id="mwC7U">package</span><span class="w" id="mwC7Y"> </span><span class="nx" id="mwC7c">models</span> <span class="kn" id="mwC7g">import</span><span class="w" id="mwC7k"> </span><span class="p" id="mwC7o">(</span> <span class="s" id="mwC7s">"database/sql"</span> <span class="s" id="mwC7w">"time"</span> <span class="p" id="mwC70">)</span> <span class="kd" id="mwC74">type</span><span class="w" id="mwC78"> </span><span class="p" id="mwC8A">(</span> <span class="w" id="mwC8E"> </span><span class="nx" id="mwC8I">UserStorage</span><span class="w" id="mwC8M"> </span><span class="kd" id="mwC8Q">struct</span><span class="w" id="mwC8U"> </span><span class="p" id="mwC8Y">{</span> <span class="w" id="mwC8c"> </span><span class="nx" id="mwC8g">conn</span><span class="w" id="mwC8k"> </span><span class="o" id="mwC8o">*</span><span class="nx" id="mwC8s">sql</span><span class="p" id="mwC8w">.</span><span class="nx" id="mwC80">DB</span> <span class="w" id="mwC84"> </span><span class="p" id="mwC88">}</span> <span class="w" id="mwC9A"> </span><span class="nx" id="mwC9E">User</span><span class="w" id="mwC9I"> </span><span class="kd" id="mwC9M">struct</span><span class="w" id="mwC9Q"> </span><span class="p" id="mwC9U">{</span> <span class="w" id="mwC9Y"> </span><span class="nx" id="mwC9c">Name</span><span class="w" id="mwC9g"> </span><span class="kt" id="mwC9k">string</span><span class="w" id="mwC9o"> </span><span class="err" id="mwC9s">'</span><span class="nx" id="mwC9w">json</span><span class="p" id="mwC90">:</span><span class="s" id="mwC94">"name"</span><span class="w" id="mwC98"> </span><span class="nx" id="mwC-A">db</span><span class="p" id="mwC-E">:</span><span class="s" id="mwC-I">"name,primarykey"</span><span class="err" id="mwC-M">'</span> <span class="w" id="mwC-Q"> </span><span class="nx" id="mwC-U">JoinedAt</span><span class="w" id="mwC-Y"> </span><span class="nx" id="mwC-c">time</span><span class="p" id="mwC-g">.</span><span class="nx" id="mwC-k">Time</span><span class="w" id="mwC-o"> </span><span class="err" id="mwC-s">'</span><span class="nx" id="mwC-w">json</span><span class="p" id="mwC-0">:</span><span class="s" id="mwC-4">"joined_at"</span><span class="w" id="mwC-8"> </span><span class="nx" id="mwC_A">db</span><span class="p" id="mwC_E">:</span><span class="s" id="mwC_I">"joined_at"</span><span class="err" id="mwC_M">'</span> <span class="w" id="mwC_Q"> </span><span class="nx" id="mwC_U">Email</span><span class="w" id="mwC_Y"> </span><span class="kt" id="mwC_c">string</span><span class="w" id="mwC_g"> </span><span class="err" id="mwC_k">'</span><span class="nx" id="mwC_o">json</span><span class="p" id="mwC_s">:</span><span class="s" id="mwC_w">"email"</span><span class="w" id="mwC_0"> </span><span class="nx" id="mwC_4">db</span><span class="p" id="mwC_8">:</span><span class="s" id="mwDAA">"email"</span><span class="err" id="mwDAE">'</span> <span class="w" id="mwDAI"> </span><span class="p" id="mwDAM">}</span> <span class="p" id="mwDAQ">)</span> <span class="kd" id="mwDAU">func</span><span class="w" id="mwDAY"> </span><span class="nx" id="mwDAc">NewUserStorage</span><span class="p" id="mwDAg">(</span><span class="nx" id="mwDAk">conn</span><span class="w" id="mwDAo"> </span><span class="o" id="mwDAs">*</span><span class="nx" id="mwDAw">sql</span><span class="p" id="mwDA0">.</span><span class="nx" id="mwDA4">DB</span><span class="p" id="mwDA8">)</span><span class="w" id="mwDBA"> </span><span class="o" id="mwDBE">*</span><span class="nx" id="mwDBI">UserStorage</span><span class="w" id="mwDBM"> </span><span class="p" id="mwDBQ">{</span> <span class="w" id="mwDBU"> </span><span class="k" id="mwDBY">return</span><span class="w" id="mwDBc"> </span><span class="o" id="mwDBg">&</span><span class="nx" id="mwDBk">UserStorage</span><span class="p" id="mwDBo">{</span> <span class="w" id="mwDBs"> </span><span class="nx" id="mwDBw">conn</span><span class="p" id="mwDB0">:</span><span class="w" id="mwDB4"> </span><span class="nx" id="mwDB8">conn</span><span class="p" id="mwDCA">,</span> <span class="w" id="mwDCE"> </span><span class="p" id="mwDCI">}</span> <span class="p" id="mwDCM">}</span> <span class="kd" id="mwDCQ">func</span><span class="w" id="mwDCU"> </span><span class="p" id="mwDCY">(</span><span class="nx" id="mwDCc">us</span><span class="w" id="mwDCg"> </span><span class="o" id="mwDCk">*</span><span class="nx" id="mwDCo">UserStorage</span><span class="p" id="mwDCs">)</span><span class="w" id="mwDCw"> </span><span class="nx" id="mwDC0">Get</span><span class="p" id="mwDC4">(</span><span class="nx" id="mwDC8">name</span><span class="w" id="mwDDA"> </span><span class="kt" id="mwDDE">string</span><span class="p" id="mwDDI">)</span><span class="w" id="mwDDM"> </span><span class="p" id="mwDDQ">(</span><span class="nx" id="mwDDU">user</span><span class="w" id="mwDDY"> </span><span class="o" id="mwDDc">*</span><span class="nx" id="mwDDg">User</span><span class="p" id="mwDDk">,</span><span class="w" id="mwDDo"> </span><span class="nx" id="mwDDs">err</span><span class="w" id="mwDDw"> </span><span class="kt" id="mwDD0">error</span><span class="p" id="mwDD4">)</span><span class="w" id="mwDD8"> </span><span class="p" id="mwDEA">{</span> <span class="w" id="mwDEE"> </span><span class="c1" id="mwDEI">// assuming 'name' is a unique key</span> <span class="w" id="mwDEM"> </span><span class="nx" id="mwDEQ">query</span><span class="w" id="mwDEU"> </span><span class="o" id="mwDEY">:=</span><span class="w" id="mwDEc"> </span><span class="s" id="mwDEg">"SELECT * FROM users WHERE name = $1"</span> <span class="w" id="mwDEk"> </span><span class="k" id="mwDEo">if</span><span class="w" id="mwDEs"> </span><span class="nx" id="mwDEw">err</span><span class="w" id="mwDE0"> </span><span class="o" id="mwDE4">:=</span><span class="w" id="mwDE8"> </span><span class="nx" id="mwDFA">us</span><span class="p" id="mwDFE">.</span><span class="nx" id="mwDFI">conn</span><span class="p" id="mwDFM">.</span><span class="nx" id="mwDFQ">QueryRow</span><span class="p" id="mwDFU">(</span><span class="nx" id="mwDFY">query</span><span class="p" id="mwDFc">,</span><span class="w" id="mwDFg"> </span><span class="nx" id="mwDFk">name</span><span class="p" id="mwDFo">).</span><span class="nx" id="mwDFs">Scan</span><span class="p" id="mwDFw">(</span><span class="o" id="mwDF0">&</span><span class="nx" id="mwDF4">user</span><span class="p" id="mwDF8">);</span><span class="w" id="mwDGA"> </span><span class="nx" id="mwDGE">err</span><span class="w" id="mwDGI"> </span><span class="o" id="mwDGM">!=</span><span class="w" id="mwDGQ"> </span><span class="kc" id="mwDGU">nil</span><span class="w" id="mwDGY"> </span><span class="p" id="mwDGc">{</span> <span class="w" id="mwDGg"> </span><span class="k" id="mwDGk">return</span><span class="w" id="mwDGo"> </span><span class="kc" id="mwDGs">nil</span><span class="p" id="mwDGw">,</span><span class="w" id="mwDG0"> </span><span class="nx" id="mwDG4">err</span> <span class="w" id="mwDG8"> </span><span class="p" id="mwDHA">}</span> <span class="w" id="mwDHE"> </span><span class="k" id="mwDHI">return</span><span class="w" id="mwDHM"> </span><span class="nx" id="mwDHQ">user</span><span class="p" id="mwDHU">,</span><span class="w" id="mwDHY"> </span><span class="kc" id="mwDHc">nil</span> <span class="p" id="mwDHg">}</span>Rust
In Rust, dependency injection is typically done through generics with static dispatch.
<span id="mwDH8"></span><span class="k" id="mwDIA">trait</span><span class="w" id="mwDIE"> </span><span class="n" id="mwDII">Logger</span><span class="w" id="mwDIM"> </span><span class="p" id="mwDIQ">{</span> <span class="w" id="mwDIU"> </span><span class="k" id="mwDIY">fn</span><span class="w" id="mwDIc"> </span><span class="nf" id="mwDIg">log</span><span class="p" id="mwDIk">(</span><span class="o" id="mwDIo">&</span><span class="bp" id="mwDIs">self</span><span class="p" id="mwDIw">,</span><span class="w" id="mwDI0"> </span><span class="n" id="mwDI4">message</span><span class="p" id="mwDI8">:</span><span class="w" id="mwDJA"> </span><span class="kp" id="mwDJE">&</span><span class="kt" id="mwDJI">str</span><span class="p" id="mwDJM">);</span> <span class="p" id="mwDJQ">}</span> <span class="k" id="mwDJU">struct</span><span class="w" id="mwDJY"> </span><span class="nc" id="mwDJc">ConsoleLogger</span><span class="p" id="mwDJg">;</span> <span class="k" id="mwDJk">impl</span><span class="w" id="mwDJo"> </span><span class="n" id="mwDJs">Logger</span><span class="w" id="mwDJw"> </span><span class="k" id="mwDJ0">for</span><span class="w" id="mwDJ4"> </span><span class="n" id="mwDJ8">ConsoleLogger</span><span class="w" id="mwDKA"> </span><span class="p" id="mwDKE">{</span> <span class="w" id="mwDKI"> </span><span class="k" id="mwDKM">fn</span><span class="w" id="mwDKQ"> </span><span class="nf" id="mwDKU">log</span><span class="p" id="mwDKY">(</span><span class="o" id="mwDKc">&</span><span class="bp" id="mwDKg">self</span><span class="p" id="mwDKk">,</span><span class="w" id="mwDKo"> </span><span class="n" id="mwDKs">message</span><span class="p" id="mwDKw">:</span><span class="w" id="mwDK0"> </span><span class="kp" id="mwDK4">&</span><span class="kt" id="mwDK8">str</span><span class="p" id="mwDLA">)</span><span class="w" id="mwDLE"> </span><span class="p" id="mwDLI">{</span> <span class="w" id="mwDLM"> </span><span class="fm" id="mwDLQ">println!</span><span class="p" id="mwDLU">(</span><span class="s" id="mwDLY">"{message}"</span><span class="p" id="mwDLc">);</span> <span class="w" id="mwDLg"> </span><span class="p" id="mwDLk">}</span> <span class="p" id="mwDLo">}</span> <span class="k" id="mwDLs">struct</span><span class="w" id="mwDLw"> </span><span class="nc" id="mwDL0">UserService</span><span class="o" id="mwDL4"><</span><span class="n" id="mwDL8">L</span><span class="p" id="mwDMA">:</span><span class="w" id="mwDME"> </span><span class="nc" id="mwDMI">Logger</span><span class="o" id="mwDMM">></span><span class="w" id="mwDMQ"> </span><span class="p" id="mwDMU">{</span> <span class="w" id="mwDMY"> </span><span class="n" id="mwDMc">logger</span><span class="p" id="mwDMg">:</span><span class="w" id="mwDMk"> </span><span class="nc" id="mwDMo">L</span><span class="p" id="mwDMs">,</span> <span class="p" id="mwDMw">}</span> <span class="k" id="mwDM0">impl</span><span class="o" id="mwDM4"><</span><span class="n" id="mwDM8">L</span><span class="p" id="mwDNA">:</span><span class="w" id="mwDNE"> </span><span class="nc" id="mwDNI">Logger</span><span class="o" id="mwDNM">></span><span class="w" id="mwDNQ"> </span><span class="n" id="mwDNU">UserService</span><span class="o" id="mwDNY"><</span><span class="n" id="mwDNc">L</span><span class="o" id="mwDNg">></span><span class="w" id="mwDNk"> </span><span class="p" id="mwDNo">{</span> <span class="w" id="mwDNs"> </span><span class="k" id="mwDNw">fn</span><span class="w" id="mwDN0"> </span><span class="nf" id="mwDN4">new</span><span class="p" id="mwDN8">(</span><span class="n" id="mwDOA">logger</span><span class="p" id="mwDOE">:</span><span class="w" id="mwDOI"> </span><span class="nc" id="mwDOM">L</span><span class="p" id="mwDOQ">)</span><span class="w" id="mwDOU"> </span><span class="p" id="mwDOY">-></span><span class="w" id="mwDOc"> </span><span class="nc" id="mwDOg">Self</span><span class="w" id="mwDOk"> </span><span class="p" id="mwDOo">{</span> <span class="w" id="mwDOs"> </span><span class="bp" id="mwDOw">Self</span><span class="w" id="mwDO0"> </span><span class="p" id="mwDO4">{</span><span class="w" id="mwDO8"> </span><span class="n" id="mwDPA">logger</span><span class="w" id="mwDPE"> </span><span class="p" id="mwDPI">}</span> <span class="w" id="mwDPM"> </span><span class="p" id="mwDPQ">}</span> <span class="w" id="mwDPU"> </span><span class="k" id="mwDPY">fn</span><span class="w" id="mwDPc"> </span><span class="nf" id="mwDPg">create_user</span><span class="p" id="mwDPk">(</span><span class="o" id="mwDPo">&</span><span class="bp" id="mwDPs">self</span><span class="p" id="mwDPw">,</span><span class="w" id="mwDP0"> </span><span class="n" id="mwDP4">name</span><span class="p" id="mwDP8">:</span><span class="w" id="mwDQA"> </span><span class="kp" id="mwDQE">&</span><span class="kt" id="mwDQI">str</span><span class="p" id="mwDQM">)</span><span class="w" id="mwDQQ"> </span><span class="p" id="mwDQU">{</span> <span class="w" id="mwDQY"> </span><span class="bp" id="mwDQc">self</span><span class="p" id="mwDQg">.</span><span class="n" id="mwDQk">logger</span><span class="p" id="mwDQo">.</span><span class="n" id="mwDQs">log</span><span class="p" id="mwDQw">(</span><span class="o" id="mwDQ0">&</span><span class="fm" id="mwDQ4">format!</span><span class="p" id="mwDQ8">(</span><span class="s" id="mwDRA">"Creating user: {name}"</span><span class="p" id="mwDRE">));</span> <span class="w" id="mwDRI"> </span><span class="c1" id="mwDRM">// Business logic...</span> <span class="w" id="mwDRQ"> </span><span class="p" id="mwDRU">}</span> <span class="p" id="mwDRY">}</span> <span class="k" id="mwDRc">fn</span><span class="w" id="mwDRg"> </span><span class="nf" id="mwDRk">main</span><span class="p" id="mwDRo">()</span><span class="w" id="mwDRs"> </span><span class="p" id="mwDRw">{</span> <span class="w" id="mwDR0"> </span><span class="kd" id="mwDR4">let</span><span class="w" id="mwDR8"> </span><span class="n" id="mwDSA">logger</span><span class="w" id="mwDSE"> </span><span class="o" id="mwDSI">=</span><span class="w" id="mwDSM"> </span><span class="n" id="mwDSQ">ConsoleLogger</span><span class="p" id="mwDSU">;</span> <span class="w" id="mwDSY"> </span><span class="kd" id="mwDSc">let</span><span class="w" id="mwDSg"> </span><span class="n" id="mwDSk">service</span><span class="w" id="mwDSo"> </span><span class="o" id="mwDSs">=</span><span class="w" id="mwDSw"> </span><span class="n" id="mwDS0">UserService</span><span class="p" id="mwDS4">::</span><span class="n" id="mwDS8">new</span><span class="p" id="mwDTA">(</span><span class="n" id="mwDTE">logger</span><span class="p" id="mwDTI">);</span> <span class="w" id="mwDTM"> </span><span class="n" id="mwDTQ">service</span><span class="p" id="mwDTU">.</span><span class="n" id="mwDTY">create_user</span><span class="p" id="mwDTc">(</span><span class="s" id="mwDTg">"Alice"</span><span class="p" id="mwDTk">);</span> <span class="p" id="mwDTo">}</span>However, it can also be done using dynamic dispatch with trait objects:
<span id="mwDT8"></span><span class="k" id="mwDUA">trait</span><span class="w" id="mwDUE"> </span><span class="n" id="mwDUI">Logger</span><span class="w" id="mwDUM"> </span><span class="p" id="mwDUQ">{</span> <span class="w" id="mwDUU"> </span><span class="k" id="mwDUY">fn</span><span class="w" id="mwDUc"> </span><span class="nf" id="mwDUg">log</span><span class="p" id="mwDUk">(</span><span class="o" id="mwDUo">&</span><span class="bp" id="mwDUs">self</span><span class="p" id="mwDUw">,</span><span class="w" id="mwDU0"> </span><span class="n" id="mwDU4">message</span><span class="p" id="mwDU8">:</span><span class="w" id="mwDVA"> </span><span class="kp" id="mwDVE">&</span><span class="kt" id="mwDVI">str</span><span class="p" id="mwDVM">);</span> <span class="p" id="mwDVQ">}</span> <span class="k" id="mwDVU">struct</span><span class="w" id="mwDVY"> </span><span class="nc" id="mwDVc">ConsoleLogger</span><span class="p" id="mwDVg">;</span> <span class="k" id="mwDVk">impl</span><span class="w" id="mwDVo"> </span><span class="n" id="mwDVs">Logger</span><span class="w" id="mwDVw"> </span><span class="k" id="mwDV0">for</span><span class="w" id="mwDV4"> </span><span class="n" id="mwDV8">ConsoleLogger</span><span class="w" id="mwDWA"> </span><span class="p" id="mwDWE">{</span> <span class="w" id="mwDWI"> </span><span class="k" id="mwDWM">fn</span><span class="w" id="mwDWQ"> </span><span class="nf" id="mwDWU">log</span><span class="p" id="mwDWY">(</span><span class="o" id="mwDWc">&</span><span class="bp" id="mwDWg">self</span><span class="p" id="mwDWk">,</span><span class="w" id="mwDWo"> </span><span class="n" id="mwDWs">message</span><span class="p" id="mwDWw">:</span><span class="w" id="mwDW0"> </span><span class="kp" id="mwDW4">&</span><span class="kt" id="mwDW8">str</span><span class="p" id="mwDXA">)</span><span class="w" id="mwDXE"> </span><span class="p" id="mwDXI">{</span> <span class="w" id="mwDXM"> </span><span class="fm" id="mwDXQ">println!</span><span class="p" id="mwDXU">(</span><span class="s" id="mwDXY">"{message}"</span><span class="p" id="mwDXc">);</span> <span class="w" id="mwDXg"> </span><span class="p" id="mwDXk">}</span> <span class="p" id="mwDXo">}</span> <span class="k" id="mwDXs">struct</span><span class="w" id="mwDXw"> </span><span class="nc" id="mwDX0">UserService</span><span class="w" id="mwDX4"> </span><span class="p" id="mwDX8">{</span> <span class="w" id="mwDYA"> </span><span class="n" id="mwDYE">logger</span><span class="p" id="mwDYI">:</span><span class="w" id="mwDYM"> </span><span class="nb" id="mwDYQ">Box</span><span class="o" id="mwDYU"><</span><span class="k" id="mwDYY">dyn</span><span class="w" id="mwDYc"> </span><span class="n" id="mwDYg">Logger</span><span class="o" id="mwDYk">></span><span class="p" id="mwDYo">,</span> <span class="p" id="mwDYs">}</span> <span class="k" id="mwDYw">impl</span><span class="w" id="mwDY0"> </span><span class="n" id="mwDY4">UserService</span><span class="w" id="mwDY8"> </span><span class="p" id="mwDZA">{</span> <span class="w" id="mwDZE"> </span><span class="k" id="mwDZI">fn</span><span class="w" id="mwDZM"> </span><span class="nf" id="mwDZQ">new</span><span class="p" id="mwDZU">(</span><span class="n" id="mwDZY">logger</span><span class="p" id="mwDZc">:</span><span class="w" id="mwDZg"> </span><span class="nb" id="mwDZk">Box</span><span class="o" id="mwDZo"><</span><span class="k" id="mwDZs">dyn</span><span class="w" id="mwDZw"> </span><span class="n" id="mwDZ0">Logger</span><span class="o" id="mwDZ4">></span><span class="p" id="mwDZ8">)</span><span class="w" id="mwDaA"> </span><span class="p" id="mwDaE">-></span><span class="w" id="mwDaI"> </span><span class="nc" id="mwDaM">Self</span><span class="w" id="mwDaQ"> </span><span class="p" id="mwDaU">{</span> <span class="w" id="mwDaY"> </span><span class="bp" id="mwDac">Self</span><span class="w" id="mwDag"> </span><span class="p" id="mwDak">{</span><span class="w" id="mwDao"> </span><span class="n" id="mwDas">logger</span><span class="w" id="mwDaw"> </span><span class="p" id="mwDa0">}</span> <span class="w" id="mwDa4"> </span><span class="p" id="mwDa8">}</span> <span class="w" id="mwDbA"> </span><span class="k" id="mwDbE">fn</span><span class="w" id="mwDbI"> </span><span class="nf" id="mwDbM">create_user</span><span class="p" id="mwDbQ">(</span><span class="o" id="mwDbU">&</span><span class="bp" id="mwDbY">self</span><span class="p" id="mwDbc">,</span><span class="w" id="mwDbg"> </span><span class="n" id="mwDbk">name</span><span class="p" id="mwDbo">:</span><span class="w" id="mwDbs"> </span><span class="kp" id="mwDbw">&</span><span class="kt" id="mwDb0">str</span><span class="p" id="mwDb4">)</span><span class="w" id="mwDb8"> </span><span class="p" id="mwDcA">{</span> <span class="w" id="mwDcE"> </span><span class="bp" id="mwDcI">self</span><span class="p" id="mwDcM">.</span><span class="n" id="mwDcQ">logger</span><span class="p" id="mwDcU">.</span><span class="n" id="mwDcY">log</span><span class="p" id="mwDcc">(</span><span class="o" id="mwDcg">&</span><span class="fm" id="mwDck">format!</span><span class="p" id="mwDco">(</span><span class="s" id="mwDcs">"Creating user: {name}"</span><span class="p" id="mwDcw">));</span> <span class="w" id="mwDc0"> </span><span class="p" id="mwDc4">}</span> <span class="p" id="mwDc8">}</span> <span class="k" id="mwDdA">fn</span><span class="w" id="mwDdE"> </span><span class="nf" id="mwDdI">main</span><span class="p" id="mwDdM">()</span><span class="w" id="mwDdQ"> </span><span class="p" id="mwDdU">{</span> <span class="w" id="mwDdY"> </span><span class="kd" id="mwDdc">let</span><span class="w" id="mwDdg"> </span><span class="n" id="mwDdk">logger</span><span class="w" id="mwDdo"> </span><span class="o" id="mwDds">=</span><span class="w" id="mwDdw"> </span><span class="nb" id="mwDd0">Box</span><span class="p" id="mwDd4">::</span><span class="n" id="mwDd8">new</span><span class="p" id="mwDeA">(</span><span class="n" id="mwDeE">ConsoleLogger</span><span class="p" id="mwDeI">);</span> <span class="w" id="mwDeM"> </span><span class="kd" id="mwDeQ">let</span><span class="w" id="mwDeU"> </span><span class="n" id="mwDeY">service</span><span class="w" id="mwDec"> </span><span class="o" id="mwDeg">=</span><span class="w" id="mwDek"> </span><span class="n" id="mwDeo">UserService</span><span class="p" id="mwDes">::</span><span class="n" id="mwDew">new</span><span class="p" id="mwDe0">(</span><span class="n" id="mwDe4">logger</span><span class="p" id="mwDe8">);</span> <span class="w" id="mwDfA"> </span><span class="n" id="mwDfE">service</span><span class="p" id="mwDfI">.</span><span class="n" id="mwDfM">create_user</span><span class="p" id="mwDfQ">(</span><span class="s" id="mwDfU">"Alice"</span><span class="p" id="mwDfY">);</span> <span class="p" id="mwDfc">}</span>
