Spring -- dependency injection

Posted by M2tM on Wed, 09 Mar 2022 16:33:48 +0100

Spring -- dependency injection

Dependency injection (DI)

Dependency injection (DI) is a process through which an object can only define its dependencies (that is, other objects working with them) through constructor parameters, factory method parameters, or properties set on the object instance after constructing or creating the object instance. Returned from factory method. The container then injects those dependencies when creating the bean. Fundamentally speaking, this process is the inverse process of the bean itself that controls the instantiation or location of its dependencies by using the direct construction of the class or the service locator pattern (so it is called Control Inversion).

Using DI principle, the code is more concise, and decoupling is more effective when providing dependencies for objects. The object does not look for its dependencies, nor does it know the location or class of the dependencies. As a result, your classes become easier to test, especially when dependencies depend on interfaces or abstract base classes, which allow the use of stubs or mock implementations in unit tests.

There are two main variants of DI: constructor based dependency injection and Setter based dependency injection.

1. Constructor injection

1. Create objects using parameterless construction (default)

  public User() {
    }

2. Create objects with parametric construction

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
  • 1. Subscript index of constructor parameter (starting from 0)

    You can use the index attribute to explicitly specify the index of the constructor parameter

    <bean id="user" class="com.cheng.pojo.User">
        <constructor-arg index="0" value="spring"></constructor-arg>
        <constructor-arg index="1" value="3"></constructor-arg>
    </bean>
    
  • 2. Constructor parameter type matching

    If the type of the constructor parameter is explicitly specified using the type attribute, the container can use type matching of simple types. It is not recommended to use when there are two parameters of the same type.

    <bean id="user" class="com.cheng.pojo.User">
        <constructor-arg type="java.lang.String" value="spring"></constructor-arg>
        <constructor-arg type="int" value="3"></constructor-arg>
    </bean>
    
  • 3. Constructor parameter name

    You can use constructor parameter names to disambiguate:

    <bean id="user" class="com.cheng.pojo.User">
        <constructor-arg name="name" value="spring"/>
        <constructor-arg name="age" value="3"/>
    </bean>
    

2. Set injection mode (common)

  • Dependency injection: Set injection
    • Dependency: the creation of bean objects depends on the container
    • Injection: all attributes in the bean object are injected by the container

Build environment

  • 1. Complex type

    package com.cheng.pojo;
    
    public class Address {
        private String address;
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
        @Override
        public String toString() {
            return "Address{" +
                    "address='" + address + '\'' +
                    '}';
        }
    }
    
    package com.cheng.pojo;
    
    import java.util.*;
    
    public class Student {
        private  String name;
        private Address address;
        private String[] books;
        private List<String> hobbys;
        private Map<String,String> card;
        private Set<String> games;
        private String wife;
        private Properties info;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Address getAddress() {
            return address;
        }
    
        public void setAddress(Address address) {
            this.address = address;
        }
    
        public String[] getBooks() {
            return books;
        }
    
        public void setBooks(String[] books) {
            this.books = books;
        }
    
        public List<String> getHobbys() {
            return hobbys;
        }
    
        public void setHobbys(List<String> hobbys) {
            this.hobbys = hobbys;
        }
    
        public Map<String, String> getCard() {
            return card;
        }
    
        public void setCard(Map<String, String> card) {
            this.card = card;
        }
    
        public Set<String> getGames() {
            return games;
        }
    
        public void setGames(Set<String> games) {
            this.games = games;
        }
    
        public String getWife() {
            return wife;
        }
    
        public void setWife(String wife) {
            this.wife = wife;
        }
    
        public Properties getInfo() {
            return info;
        }
    
        public void setInfo(Properties info) {
            this.info = info;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", address=" + address.toString() +
                    ", books=" + Arrays.toString(books) +
                    ", hobbys=" + hobbys +
                    ", card=" + card +
                    ", games=" + games +
                    ", wife='" + wife + '\'' +
                    ", info=" + info +
                    '}';
        }
    }
    
  • 2. Real test object

    //Implement the injection of all the following attributes
    private  String name;
    private Address address;
    private String[] books;
    private List<String> hobbys;
    private Map<String,String> card;
    private Set<String> games;
    private String wife;
    private Properties info;
    
  • 3.applicationContext.xml

    <?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
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="address" class="com.cheng.pojo.Address"></bean>
    
        <bean id="student" class="com.cheng.pojo.Student">
            <!--The first: injection of ordinary value, with value-->
            <property name="name" value="a great distance"/>
            <!--Second: bean Injection of, ref-->
            <property name="address" ref="address"/>
            <!--Third: array injection-->
            <property name="books" >
                <array>
                    <value>Journey to the West</value>
                    <value>The Dream of Red Mansion</value>
                    <value>Water Margin</value>
                    <value>Romance of the Three Kingdoms</value>
                </array>
            </property>
            <!--Fourth: List injection-->
            <property name="hobbys">
                <list>
                    <value>Play games</value>
                    <value>watch movie</value>
                    <value>Knock code</value>
                </list>
            </property>
            <!--Fifth: Map injection-->
            <property name="card">
                <map>
                    <entry key="full name" value="a great distance"/>
                    <entry key="Department" value="Department of Information Engineering"/>
                    <entry key="grade" value="18 level"/>
                    <entry key="major" value="Computer science and technology"/>
                </map>
            </property>
            <!--Sixth: Set injection-->
            <property name="games">
                <set>
                    <value>LOL</value>
                    <value>COC</value>
                    <value>BOB</value>
                </set>
            </property>
            <!--Seventh: Null injection-->
            <property name="wife">
                <null/>  <!--Equivalent to student.setWife(null);-->
            </property>
    <!--<property name="wife" value=""> Equivalent to student.setWife(""); take wife Property is set to an empty string value-->
    
            <!--Eighth: properties injection-->
            <property name="info">
                <props>
                    <prop key="Student number">08090335615</prop>
                    <prop key="full name">a great distance</prop>
                </props>
            </property>
        </bean>
    </beans>
    
  • 4. Testing

    import com.cheng.pojo.Student;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MyTest {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            Student student = (Student) context.getBean("student");
            System.out.println(student.toString());
        }
    }
    
    

    Test results:

    Student{name='a great distance', address=Address{address='null'}, 
    books=[Journey to the West, The Dream of Red Mansion, Water Margin, Romance of the Three Kingdoms], 
    hobbys=[Play games, watch movie, Knock code], 
    card={full name=a great distance, Department=Department of Information Engineering, grade=18 level, major=Computer science and technology}, 
    games=[LOL, COC, BOB], 
    wife='null', 
    info={Student number=08090335615, full name=a great distance}}
    

3. Expansion mode injection

p namespace injection and c namespace injection cannot be used directly and need to import constraints

P namespace injection xmlns:p=“ http://www.springframework.org/schema/p ”

C namespace injection xmlns:c=“ http://www.springframework.org/schema/c ”

1. Environmental construction

package com.cheng.pojo;

public class User {
    private String name;
    private int age;
    private Address address;

    public User() {
    }

    public String getName() {
        return name;
    }

    public User(String name, int age, Address address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                '}';
    }
}

2.userbeans.xml

  • p namespace injection

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:p="http://www.springframework.org/schema/p"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!--p Namespace injection, you can directly inject the value of the attribute,You can also inject references-->
        <bean id="user" class="com.cheng.pojo.User"
              p:name="a great distance"
              p:age="3"
              p:address-ref="address"/>
    </beans>
    
  • c namespace injection

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:c="http://www.springframework.org/schema/c"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!--c Namespace injection, through constructor injection, construct-org -->
        <bean id="user2" class="com.cheng.pojo.User" c:name="a great distance" c:age="3" c:address-ref="address"/>
    </beans>
    

Test class

    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = context.getBean("user2", User.class);//After using reflection, there is no need to type strong rotation
        System.out.println(user);
}

Topics: Spring bean DI