For a long time, THE concept of INVERSION of control and dependency injection (DI) was very vague, and I felt dizzy when I closed my eyes and thought about it. But in order to become a good Java engineer, I spent a week figuring them all out.

01. Tight coupling

In the process of coding, two or more classes are usually required to cooperate with each other to realize the business logic, that is to say, an object needs to obtain the reference of its partner object. If the process of obtaining the reference needs to be realized by itself, the coupling degree of the code will be high and the cost of maintenance will be relatively high.

Let’s do it in real life. If Lao Wang is the president of the Shaolin Temple, he wants to let the small two monks to sweep the dharma hospital, the code can be implemented in this way.

The code for the minor class is as follows:

public class Xiaoer {
	public void saodi(a) {
		System.out.println("I am sweeping the floor of the Dharma Courtyard."); }}Copy the code

The code for the Lao Wang class is as follows:

public class Laowang {
	public void mingling(a) {
		newXiaoer().saodi(); }}Copy the code

The code for the test class looks like this:

public class Test {

	public static void main(String[] args) {
		Laowang laowang = newLaowang(); laowang.mingling(); }}Copy the code

The mingling method of the Laowang class uses the new keyword to create an object of the Xiaoer class. This code is highly coupled and expensive to maintain.

One day, the dharma hospital is dirty, Laowang chair remembered the little two monk, but the little two monk to practice yi jin jing, let who go to sweep the floor, Laowang chair remembered the little three monk, so Laowang class had to re next a new command, so the code became like this:

public class Xiaosan {
    public void saodi(a) {
        System.out.println("Mistress, I am sweeping the floor of the Dharma Courtyard."); }}public class Laowang {
    public void mingling(a) {
        new Xiaoer().saodi();
    }

    public void mingling1(a) {
        newXiaosan().saodi(); }}Copy the code

If the third monk went to carry water, Lao Wang might order the fourth monk to sweep the dharma courtyard. At this rate, the Laowang class will go crazy.

Lao Wang felt that he was an eminent monk, and he felt very unhappy that he had given such a troublesome order to sweep the floor.

02. Inversion of control

We have to figure out a way for Host Wang, don’t we?

It would be better to give the job of sweeping the floor to Lao Fang, Lao Wang’s junior brother. Lao Fang is responsible for asking the second monk or the third monk or the fourth monk to carry out Lao Wang’s orders. The code can be implemented like this.

Define a sweeping monk interface as follows:

public interface Heshang {
    void saodi(a);
}
Copy the code

The code changes for the minor class are as follows:

public class Xiaoer implements Heshang {

    @Override
    public void saodi(a) {
        System.out.println("I am sweeping the floor of the Dharma Courtyard.");        
    }

    public boolean isYijinjing(a) {
        // On Wednesday, the second monk will practice yi Jin Sutra
        return false; }}Copy the code

The code changes for subclass 3 are as follows:

public class Xiaosan implements Heshang {

    @Override
    public void saodi(a) {
        System.out.println("Mistress, I am sweeping the floor of the Dharma Courtyard."); }}Copy the code

The code for the old square class looks like this:

public class Laofang {
    public static Heshang getSaodiseng(a) {
        Xiaoer xiaoer = new Xiaoer();
        if (xiaoer.isYijinjing()) {
            return new Xiaosan();
        }
        returnxiaoer; }}Copy the code

If the old side confirms that Monk Xiao Er is practicing yi Jin Sutra, he will call monk Xiao SAN.

The code of the Lao Wang class is modified as follows:

public class Laowang {
    public void mingling(a) { Laofang.getSaodiseng().saodi(); }}Copy the code

The code for the test class does not change, as follows:

public class Test {

    public static void main(String[] args) {
        Laowang laowang = newLaowang(); laowang.mingling(); }}Copy the code

Lao Wang had no worries now. His younger brother Lao Fang was in charge of who should be ordered to sweep the dharma courtyard.

The solution we had in mind for Mr. Wang was called Inversion of Control, and it was not a technology, but an idea that guided us in designing loose-coupled programs.

The meaning of inversion of control can be divided into “control” and “inversion”. When it comes to control, we must find out the subject and object, who controls whom; When it comes to inversion, you have to know what a forward is.

You see, in the tightly coupled case, when the old wang commands, he creates the dependent object himself with the new keyword (small second monk or small third monk); After the reversal of control, the sweeping monk Lao Wang wanted to find was in charge of his junior brother Lao Fang, that is to say, the control was handed over to Lao Fang, was it reversed?

03. Dependency injection

Dependency Injection (DI) is the main way to achieve inversion of control: dependent B objects are created during the creation of an instance of class A, and different objects are injected into different properties by type or name. There are roughly three specific implementations:

1) Based on constructors. Implements a constructor for a particular parameter that passes in an object of the dependent type when creating a new object.

The code of the Lao Wang class is modified as follows:

public class Laowang {
    private Heshang saodiseng;
    
    public Laowang(Heshang saodiseng) {
        this.saodiseng = saodiseng;
    }
    public void mingling(a) {
       this.saodiseng.saodi(); }}Copy the code

The code changes for the test class are as follows:

public class Test {

    public static void main(String[] args) {
        Laowang laowang = new Laowang(newXiaosan()); laowang.mingling(); }}Copy the code

At this point, control is in the hands of the test class, which decides whether to send the little second monk or the little third monk to carry out Lao Wang’s sweeping orders.

2) Based on set method. Implement a public set method for a particular property and let the external container call in an object of the dependent type.

The code of the Lao Wang class is modified as follows:

public class Laowang {
    private Heshang saodiseng;
    
    public Heshang getSaodiseng(a) {
        return saodiseng;
    }

    public void setSaodiseng(Heshang saodiseng) {
        this.saodiseng = saodiseng;
    }

    public void mingling(a) {
       this.getSaodiseng().saodi(); }}Copy the code

The code changes for the test class are as follows:

public class Test {

    public static void main(String[] args) {
        Laowang laowang = new Laowang();
        Xiaosan xiaosan = newXiaosan(); laowang.setSaodiseng(xiaosan); laowang.mingling(); }}Copy the code

At this point, control is still in the hands of the test class, which decides whether to send the little Second monk or the little third Monk to carry out Lao Wang’s sweeping orders.

3) Based on interface. Implementing a specific interface for external containers to inject objects of a dependent type is more complex than constructors and set methods, which I’ll skip here.

Some might equate INVERSION of control with dependency injection, but they are fundamentally different: Inversion of control is an idea, while dependency injection is a form of implementing inversion of control.

04. Spring Framework

Once we understand the concepts of inversion of control and dependency injection, we can take a quick look at the well-known Spring framework. Inversion of control is at the heart of the Spring framework throughout. Spring has two implementations of dependency injection: set (passing values) and constructor (referencing).

First, we need to add Spring’s dependencies to the POM.xml file as follows:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>4.3.2. RELEASE</version>
</dependency>
Copy the code

Second, we change the Laowang class to the following:

public class Laowang {
    private Heshang saodiseng;
    
    public Laowang(Heshang saodiseng) {
        this.saodiseng = saodiseng;
    }
    public void mingling(a) {
       this.saodiseng.saodi(); }}Copy the code

We then create a Spring configuration file, application.xml, that looks like this:

<? xml version="1.0" encoding="UTF-8"? > <beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean id="laowang" class="com.cmower.java_demo.ioc.Laowang">
    <constructor-arg ref="saodiseng" />
  </bean>
        
  <bean id="saodiseng" class="com.cmower.java_demo.ioc.Xiaosan" />

</beans>
Copy the code

The element configures two objects, one Lao Wang, and one junior monk, using the element to take the junior monk as the construction parameter of Lao Wang.

After the preparation is complete, let’s test it, with the following code example:

public class Test {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        Laowang laowang = (Laowang) context.getBean("laowang"); laowang.mingling(); }}Copy the code

You see, we gave control to the IoC framework Spring, which also perfectly solved the problem of tight coupling in our code.

05, finally

To sum up:

1) Inversion of control is an idea of decoupling in software engineering, giving control to a third party who decides at runtime to “inject” specific dependent objects into the objects of the calling class.

2) Dependency injection can be used as an implementation of inversion of control, passing instance variables into an object.

3) Through the IoC framework, the strong coupling between class A and class B can be established at run time through the container, that is, the creation of instances of B is handed over to the container, and class A can just use it.

Welcome to pay attention to “Silent King ii” public account, background reply keyword “Java” you can get free “Java programmers advanced required reading material”.