Spring -- Essence and code example of IOC

gossip

Hahaha, I've been reading computer network books recently. I'm a little lazy when updating my blog. Continue today

Basic points

1. IOC essence

  • Inversion of Control (IoC) is a design principle in object-oriented programming, which can be used to reduce the coupling between computer codes.
  • Control inversion is a way to produce or obtain specific objects through description (XML or annotation) and through a third party. The IOC container implements control inversion in Spring, and its implementation method is Dependency Injection (DI)
  • IOC means giving your designed object to the container control, rather than the traditional direct control inside your object. In traditional Java SE programming, we directly create objects inside objects through new, which is the program's initiative to create dependent objects; IOC has a special container (third party) to create these objects, that is, the IOC container controls the creation of objects
  • In a word: objects are created, managed and assembled by spring

2. Understand IOC ideas through examples

1) If we want to use three different databases to query personnel data, before introducing the idea of IOC, the implementation code logic is as follows
First, we create the corresponding service interface, dao interface and corresponding entity class

public interface UserService {
    void getUserInfo();
}


import com.decade.dao.UserDao;
import com.decade.dao.UserDaoMysqlImpl;
public class UserServiceImpl implements UserService{
    // The program actively creates objects and controls the generation of objects. Each time the business changes, the original code needs to be adjusted
    private UserDao userDao = new UserDaoMysqlImpl();
    
    // For example, if we want to use Oracle database for query, we need to adjust the source code here, which violates the opening and closing principle
    // private UserDao userDao = new UserDaoOracleImpl();

    @Override
    public void getUserInfo() {
        userDao.queryUserInfo();
    }
}

public interface UserDao {
    void queryUserInfo();
}

public class UserDaoMysqlImpl implements UserDao{
    @Override
    public void queryUserInfo() {
        System.out.println("utilize MySQL Query employee information");
    }
}

public class UserDaoOracleImpl implements UserDao{
    @Override
    public void queryUserInfo() {
        System.out.println("utilize Oracle Query employee information");
    }
}

public class UserDaoSqlServerImpl implements UserDao{
    @Override
    public void queryUserInfo() {
        System.out.println("utilize SqlServer Query employee information");
    }
}

Then the test class

import com.decade.service.UserService;
import com.decade.service.UserServiceImpl;

public class MyTest {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        userService.getUserInfo();
    }
}

2) In order to solve the problem that the source code needs to be adjusted due to business changes, we add a set method to realize the dynamic injection of dao objects

import com.decade.dao.UserDao;

public class UserServiceImpl implements UserService{

    private UserDao userDao;

    // Dynamic injection of dao objects using set
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void getUserInfo() {
        userDao.queryUserInfo();
    }
}

In the test class, we can specify which database corresponding implementation class to use, and the initiative to create objects is transferred from the program to the customer

import com.decade.dao.UserDaoOracleImpl;
import com.decade.service.UserService;
import com.decade.service.UserServiceImpl;

public class MyTest {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();

        // You can decide which implementation class to use for the query here
        ((UserServiceImpl) userService).setUserDao(new UserDaoOracleImpl());

        userService.getUserInfo();
    }
}

In this way, the program no longer has the initiative to create objects, but passively receives objects. This idea essentially solves the problem. We don't need to pay attention to the creation of objects, and the coupling of the system is greatly reduced. We can focus on business development, which is the prototype of IOC.

3. Implementation method and code example of IOC in spring

IOC can be implemented in a variety of ways, using XML configuration or annotations
During initialization, the Spring container reads the configuration file first, creates and organizes objects according to the configuration file or metadata, and stores them in the container. When the program is used, it takes out the required objects from the IOC container

1) When configuring a Bean in XML, the definition information of the Bean is separated from the implementation code

For details, please refer to: Spring - DI dependency injection set injection in

Thus, we can use the above example of using different data to query personnel information, and we can also trust the creation of objects to spring
We only need to create a bean configuration file to complete the relevant configuration of the object

<?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">

    <!-- If there are other new scenarios, you can directly configure them here after writing the implementation class -->
    <bean id="mysql" class="com.decade.dao.UserDaoMysqlImpl"/>
    <bean id="oracle" class="com.decade.dao.UserDaoOracleImpl"/>
    <bean id="sqlServer" class="com.decade.dao.UserDaoSqlServerImpl"/>

    <bean id="userServiceImpl" class="com.decade.service.UserServiceImpl">
        <!--
        ref:Used to reference spring Created object in container
        value:Set to specific value, basic data type
        If the user wants to use Oracle Check the database and put it here ref Replace the referenced object with Oracle dependent bean that will do
         -->
        <property name="userDao" ref="mysql"/>
    </bean>
</beans>

The corresponding test class code is. If you want to adjust the use of different databases for query, we can adjust the ref reference value of the corresponding implementation class bean in the above xml file

import com.decade.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest2 {
    public static void main(String[] args) {
        // Get spring's container
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        // Get the required object from the context object
        UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("userServiceImpl");
        userServiceImpl.getUserInfo();
    }
}

The operation results are as follows

2) When annotation is adopted, the definition information and implementation of Bean are integrated. The definition information of Bean is directly defined in the implementation class in the form of annotation, so as to achieve the purpose of zero configuration

If there is any mistake, please correct it

Keywords: Java Spring Back-end

Added by ipruthi on Sun, 09 Jan 2022 10:25:50 +0200