From translator
The translation presented to your attention opens up a series of articles on dependency injection, or DI, by Jakob Jenkov. Noteworthy is the series in that the author analyzes the concepts and practical application of such concepts as “dependency”, “dependency injection”, “dependency injection container”, comparing object creation patterns, analyzing shortcomings of specific implementations of DI containers (for example, Spring) , tells how he came to writing his own DI-container. Thus, the reader is invited to get acquainted with a fairly solid look at the issue of dependency management in applications.
This article compares the approach to setting up objects from inside and outside (DI). In the meaning of this article continues the article Jakob Jenkov
Understanding Dependencies , which defines the very concept of "dependency" and their types.

')
The series includes the following articles.
- Dependency Injection
- Dependency Injection Containers
- Dependency Injection Benefits
- When to use Dependency Injection
- Is Dependency Injection Replacing the Factory Patterns?
Dependency injection
“Dependency injection” is an expression first used in a Martin Fowler article
Inversion of Control Containers and the Dependency Injection Pattern . This is a good article, but it overlooks some of the advantages of dependency injection containers. Also, I do not agree with the conclusions of the article, but this is in the following texts.
Explanation of dependency injection
Video from the author with illustrative examples of the text of the article
Dependency injection is an object configuration style in which the object fields are specified by an external entity. In other words, objects are configured by external objects. DI is an alternative to self-tuning objects. It may look a bit abstract, so let's see an example:
UPD: after discussing the code fragments presented by the author with flatscode and fogone , I decided to correct controversial points in the code. The original intention was not to touch the code and give it the way it was written by the author. The original author's code in the disputed places is commented out with the indication “in the original”, the corrected version is given below. Also, the original code can be found at the link at the beginning of the article.public class MyDao {
This DAO (Data Access Object) MyDao needs a javax.sql.DataSource instance in order to get connections to the database. Database connections are used to read and write to the database, for example, Person objects.
Notice that the MyDao class creates an instance of DataSourceImpl because it needs a data source. The fact that MyDao needs a DataSource implementation means that it depends on it. It cannot do its work without implementing the DataSource. Consequently, MyDao has a “dependency” on the DataSource interface and on some implementation of it.
The MyDao class creates an instance of DataSourceImpl as an implementation of the DataSource. Consequently, the MyDao class itself "resolves its dependencies." When a class resolves its own dependencies, it automatically also depends on the classes for which it resolves the dependencies. In this case, MyDao also comes from a DataSourceImpl and from four hard-coded string values ​​that are passed to the DataSourceImpl constructor. You can neither use other values ​​for these four lines, nor use another implementation of the DataSource interface without changing the code.
As you can see, when a class resolves its own dependencies, it becomes inflexible with respect to these dependencies. This is bad. This means that if you need to change dependencies, you need to change the code. In this example, this means that if you need to use another database, you will need to change the class MyDao. If you have many DAO classes implemented in this way, you will have to change them all. In addition, you cannot conduct unit testing on MyDao, having locked the DataSource implementation. You can only use DataSourceImpl. It doesn't take a lot of mind to realize that this is a bad idea.
Let's change the design a bit:
public class MyDao {
Notice that the creation of the DataSourceImpl instance has been moved to the constructor. The constructor takes four parameters, these are the four values ​​needed for the DataSourceImpl. Although the MyDao class still depends on these four values, it no longer resolves the dependency itself. They are provided by the class that creates the MyDao instance. Dependencies are “embedded” in the MyDao constructor. Hence the term “implementation (add. Or otherwise - injection) of dependencies.” Now it is possible to change the database driver, URL, username or password used by the MyDao class without changing it.
Dependency injection is not limited to constructors. You can embed dependencies also using setters or directly through public fields (translator disagrees about the fields, this violates the protection of class data).
MyDao class can be more independent. Now it still depends on both the DataSource interface and the DataSourceImpl class. No need to depend on anything other than the DataSource interface. This can be achieved by injecting the DataSource into the constructor instead of the four string type parameters. Here's what it looks like:
public class MyDao {
Now the MyDao class is no longer dependent on the DataSourceImpl class or on the four lines required by the DataSourceImpl constructor. Now you can use any DataSource implementation in the MyDao constructor.
Chain dependency injection
The example from the previous section is a bit simplified. You can argue that the dependency is now moved from the MyDao class to each client that uses the MyDao class. Clients now have to know about the implementation of the DataSource in order to be able to put it into the MyDao constructor. Here is an example:
public class MyBizComponent{ public void changePersonStatus(Person person, String status){ MyDao dao = new MyDao( new DataSourceImpl("driver", "url", "user", "password")); Person person = dao.readPerson(person.getId()); person.setStatus(status); dao.update(person); } }
As you can see, now MyBizComponent depends on the DataSourceImpl class and the four lines needed by its constructor. This is even worse than the dependence of MyDao on them, because MyBizComponent now depends on the classes and on information that he does not even use. Moreover, the implementation of the DataSourceImpl and the constructor parameters belong to different layers of abstraction. The layer below MyBizComponent is the DAO layer.
The solution is to continue the implementation of dependency across all layers. MyBizComponent should depend only on the MyDao instance. Here's what it looks like:
public class MyBizComponent{
Again the dependency, MyDao, is provided through the constructor. Now MyBizComponent depends only on the class MyDao. If MyDao were an interface, it would be possible to change the implementation without the knowledge of MyBizComponent.
Such a dependency injection pattern must continue through all layers of the application, from the bottommost layer (the data access layer) to the user interface (if there is one).
To top