Java’s reflection mechanism and spring framework’s IoC (inversion of control) and DI (dependency injection)

java’s reflection mechanism and spring framework’s IoC and DI

  • Overview of java reflection mechanism:
  • Advantages of Java Reflection
  • The Java reflection mechanism is widely used in the following scenarios:
  • Java reflection mainly involves the following classes and methods:
    • Class class: Indicates the type of a class, and various information about the class can be obtained.
    • Constructor class: Represents the constructor of a class.
    • Method class: Represents a method of a class.
    • Field class: Represents the attributes of a class.
  • Here are some examples using Java reflection:
  • Spring framework
    • Spring IoC (Inversion of Control)
    • Spring DI (Dependency Injection)

Overview of java reflection mechanism:

The java reflection mechanism refers to the ability to dynamically obtain class information and operate on it at runtime. Java reflection allows programmers to write code without knowing the internal structure of the class, but can obtain information such as class names, attributes, methods, etc. through the reflection mechanism, and create objects, call methods, or modify attribute values based on this information.

In short, JAVA reflection is the soul of the framework!

If you want to use reflection, you have to get the bytecode file after code compilation is the .class file

Advantages of Java reflection

  1. Create an object dynamically without knowing its concrete class name.
  2. Determine the class of the object at runtime, and dynamically call the method of the class.
  3. Get all member variables and methods of the class at runtime, including private ones.
  4. You can call methods on an object and change the values of its properties.
  5. Easy to write generic code.

The Java reflection mechanism is widely used in the following scenarios:

  1. Framework design: The framework needs to use a lot of reflection to realize functions such as dynamic loading of classes and injection of dependencies.
  2. Plug-in development: Use reflection to dynamically load the classes provided by the plug-in and call the methods defined in the Plugin interface.
  3. Code generation: By reading annotations, XML and other files, combined with the reflection mechanism, many tools for automatically generating code can be implemented.
  4. Debugging tool: Through the reflection mechanism, you can view all the methods and attributes of a class, which helps us better understand the behavior of the class.
  5. Unit testing: The reflection mechanism can easily call private methods and properties in the class for unit testing.

Java reflection mainly involves the following classes and methods:

Class class: Indicates the type of a class, and various information of the class can be obtained.

The Java reflection API provides a Class class, which contains information about the class, such as the name of the class, superclass, interface, constructor, methods, and fields. You can use this information to create new instances, execute methods, and read or set the values of fields.

Get the Class object
Every class in Java has a hidden static field class which holds a reference to the Class object representing that class. The Class object can be obtained using:

 // Method 1: Get the Class object by class name
        Class clazz1 = BookDao. class;

        // Method 2: Get the Class object through the object BookDao is the interface, and BookDaoImpl is the implementation class of the interface
        BookDao obj = new BookDaoImpl();
        Class clazz2 = obj. getClass();

        // Method 3: Obtain the Class object through the fully qualified name of the class
        Class clazz3 = Class.forName("com.yyz.dao.BookDao");

Constructor class: represents a class constructor.

get class constructor
A class’s constructor can be obtained using:

 //Load the Class object of the class through the full class name
        Class cla = Class.forName("com.yyz.sercice.impl.BookServiceImpl");
        //Class object can be considered as the scalpel of the class, which can dissect the things in the class--properties, constructors, methods

// Get an array of all public constructors (that is, public modified constructors) of this class.
        Constructor[] constructors = cla. getConstructors();
        for (Constructor constructor : constructors) {<!-- -->
            System.out.println(constructor);
        }
// Get the constructor of the specified parameter type
Constructor constructor = cla. getConstructor(String. class, Integer. class);
for (Constructor constructor1 : constructors) {<!-- -->
            System.out.println(constructor1);
        }
        // Get all constructors
Constructor[] constructors1 = cla. getDeclaredConstructors();
        for (Constructor constructor : constructors1) {<!-- -->
            System.out.println(constructor);
        }
       

Method class: represents a method of a class.


//Get the public methods in this class or interface and the public methods in its parent class.
Method[] methods = cla. getMethods();
        for (Method method : methods) {<!-- -->
            System.out.println(method);
        }
        System.out.println("-------------");
        // Get all the methods declared by the class or interface (including public, protected, default and private, etc.)
        Method[] methods1 = cla. getDeclaredMethods();
        for (Method method : methods1) {<!-- -->
            System.out.println(method);
        }

Field class: Indicates the attributes of a class.

 Field[] fields = cla.getFields(); // Only public modified attributes can be obtained
        for (Field field : fields) {<!-- -->
            System.out.println(field);
        }
        System.out.println("-------------");
        Field[] fields1 = cla.getDeclaredFields(); //Get all attributes
        for (Field field : fields1) {<!-- -->
            System.out.println(field);
        }
        // Get the attribute of the specified attribute name
Field field = cla. getField("add");
System.out.println(field);

Here are some examples using Java reflection:

Need to use the jar package jar package
hamcrest-core-1.3
junit-4.12
project structure

Build the BookDao interface first

package com.yyz.dao;

public interface BookDao {<!-- -->
    public void add();
}

then to impl

package com.yyz.dao.impl;

import com.yyz.dao.BookDao;

public class BookDaoImpl implements BookDao {<!-- -->
    @Override
    public void add() {<!-- -->
        System.out.println("BookDaoImpl...add");
    }
}

Service package
BookService

package com.yyz.service;

public interface BookService {<!-- -->
public void add();
public void fun();
}

service.impl package
BookServiceImpl

package com.yyz.service.impl;

import com.yyz.dao.BookDao;
import com.yyz.dao.impl.BookDaoImpl;
import com.yyz.service.BookService;

public class BookServiceImpl implements BookService {<!-- -->
    //Attributes of the class---storage data
    public String name;
    int age;
    protected String sex;
    private String address;

    //Construction method of the class --- used to construct the object
    public BookServiceImpl() {<!-- -->
    }

    public BookServiceImpl(String name) {<!-- -->
        this.name = name;
    }

    private BookServiceImpl(String name, int age, String sex, String address) {<!-- -->
        this.name = name;
        this. age = age;
        this. sex = sex;
        this.address = address;
    }


    BookDao bookDao=new BookDaoImpl();

    //Function method --- complete some programs or functions

    @Override
    public void add() {<!-- -->
        System.out.println("BookServiceImpl................add");
        bookDao. add();
    }

    @Override
    public void fun() {<!-- -->
        System.out.println("BookServiceImpl..........fun");
    }
}

BookServiceVip

package com.yyz.service.impl;

import com.yyz.dao.BookDao;
import com.yyz.dao.impl.BookDaoImpl;
import com.yyz.service.BookService;

public class BookServiceVip implements BookService {<!-- -->
    BookDao bookDao=new BookDaoImpl();
    @Override
    public void add() {<!-- -->
        System.out.println("BooKServiceVip...add");
        bookDao. add();
    }

    public void fun(){<!-- -->
        System.out.println("BookServiceImpl...fun");
    }
}

test package
BookServlet class

package com.yyz.servlet;

import com.yyz.service.BookService;
import com.yyz.service.impl.BookServiceVip;
import org.junit.Test;

public class BookServlet {<!-- -->

    BookService bookService=new BookServiceVip();

    @Test
    public void add(){<!-- -->
        System.out.println("BookServlet...add");
        bookService. add();
    }

}

Class Test01

package com.yyz.servlet;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Test01 {<!-- -->
    public static void main(String[] args) throws Exception {<!-- -->
        //Load the Class object of the class through the full class name
        Class cla = Class.forName("com.yyz.service.impl.BookServiceImpl");
        //Class object can be considered as the scalpel of the class, which can dissect the things in the class--properties, constructors, methods
        Field[] fields = cla.getFields(); //Only get public modified attributes
        for (Field field : fields) {<!-- -->
            System.out.println(field);
        }
        System.out.println("-------------");
        Field[] fields1 = cla.getDeclaredFields(); //Get all attributes
        for (Field field : fields1) {<!-- -->
            System.out.println(field);
        }

        System.out.println("==========================");

        Constructor[] constructors = cla. getConstructors();
        for (Constructor constructor : constructors) {<!-- -->
            System.out.println(constructor);
        }
        System.out.println("-------------");
        Constructor[] constructors1 = cla. getDeclaredConstructors();
        for (Constructor constructor : constructors1) {<!-- -->
            System.out.println(constructor);
        }

        System.out.println("==========================");
        Method[] methods = cla. getMethods();
        for (Method method : methods) {<!-- -->
            System.out.println(method);
        }
        System.out.println("-------------");
        Method[] methods1 = cla. getDeclaredMethods();
        for (Method method : methods1) {<!-- -->
            System.out.println(method);
        }
    }
}

operation result

Class Test02

package com.yyz.servlet;

import com.yyz.service.BookService;

import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.util.Properties;

public class Test02 {<!-- -->

    public static void main(String[] args) throws Exception {<!-- -->
        //Read the configuration file and get the content
        InputStream stream = Test02.class.getClassLoader().getResourceAsStream("info.properties");
        Properties p = new Properties();
        p.load(stream);
        String className=p. getProperty("className");
        //1. Get the Class object of the class through the full class name
        Class cla = Class. forName(className);
        //2. Obtain the parameterless constructor of the class through the Class object
        Constructor constructor = cla. getDeclaredConstructor();
        //3. Use the constructor to create an object
        BookService bookService = (BookService) constructor. newInstance();
        //4. Use the object to call the method
        bookService. add();
    }
    }


operation result

Class Test03

package com.yyz.servlet;

import com.yyz.service.BookService;

import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;

public class Test03 {<!-- -->

    public static void main(String[] args) throws Exception {<!-- -->
        //Read the configuration file and get the content
        InputStream stream = Test03.class.getClassLoader().getResourceAsStream("info.properties");
        Properties p = new Properties();
        p.load(stream);
        String className=p. getProperty("className");
        String methodName=p. getProperty("methodName");
        //1. Get the Class object of the class through the full class name
        Class cla = Class. forName(className);
        //2. Obtain the parameterless constructor of the class through the Class object
        Constructor constructor = cla. getDeclaredConstructor();
        //3. Use the constructor to create an object
        BookService bookService = (BookService) constructor. newInstance();
        //4. Get the method name
        Method method = cla. getDeclaredMethod(methodName);
        //5. Execution method
        method.invoke(bookService);
    }
}

operation result

Spring Framework

Spring framework
was created due to the complexity of software development. Spring uses basic JavaBeans to do things that were previously only possible with EJBs. However, the use of Spring is not limited to server-side development. The vast majority of Java applications can benefit from Spring in terms of simplicity, testability, and loose coupling.

Spring IoC (Inversion of Control)

It is one of the core features of the Spring framework, which achieves loose coupling of applications by handing over object creation and dependency management to the container. The IoC container is responsible for instantiating, configuring, and assembling objects, so that developers can focus more on writing business logic without worrying about object creation and management.

In Spring, the IoC container learns how to create and assemble objects by reading XML files or annotation configuration information. When the container starts, it will automatically scan all classes under the specified path, instantiate and store these classes in the container. When an object needs to be used, the container will create a new instance according to the definition information of the object, and automatically inject other objects that the object depends on.

The following is a simple example of using the Spring IoC container to create and manage objects:
jar package https://share.weiyun.com/AgoymFat

In the Spring framework, Dependency Injection (DI for short) is a design pattern that decouples the dependencies between objects through the container, thereby reducing the coupling and complexity of the application.

Spring DI (Dependency Injection)

DI implements the concept of “Inversion of Control” (IoC for short), which is to hand over the control of the application to the component to the container. The container is responsible for maintaining dependencies between objects and injecting dependencies into objects when appropriate.

In Spring, DI mainly has the following two implementation methods:

Constructor Injection: Inject dependencies through constructors, and pass dependencies to the object’s constructor when the object is created. This approach is very useful for required dependencies, as it ensures that the dependencies are injected when the object is created.

Property injection (Setter Injection): Inject dependencies through the setter method, and set the dependencies through the setter method after the object is created. Compared to constructor injection, property injection is more flexible because it can modify dependencies at any time after object creation.

Regardless of which method is used, Spring will automatically complete dependency injection at runtime based on configuration files or annotations. For example, define a bean in an XML configuration file and specify its required dependencies:

project structure

First create the Dao interface

package com.yyz.dao;

public interface BookDao {<!-- -->
    public void insert();
}

The implementation class that implements the dao interface

package com.yyz.dao.impl;

import com.yyz.dao.BookDao;

public class BookDaoImpl implements BookDao {<!-- -->
    @Override
    public void insert() {<!-- -->
        System.out.println("BookDaoImpl...save");
    }
}

service layer

BookService interface

package com.yyz.service;

public interface BookService {<!-- -->
 public void save();
}

Two classes that implement BookService

package com.yyz.service.impl;
import com.yyz.dao.BookDao;
import com.yyz.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;

public class BookServiceImpl implements BookService {<!-- -->
    public String name;

    public int age;

    private BookDao bookDao;

    @Override
    public String toString() {<!-- -->
        return "BookServiceImpl{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", bookDao=" + bookDao +
                '}';
    }

    public void setName(String name) {<!-- -->
        this.name = name;
    }

    public void setAge(int age) {<!-- -->
        this. age = age;
    }
    @Autowired
    public void setBookDao(BookDao bookDao) {<!-- -->
        this.bookDao = bookDao;
    }
    public BookServiceImpl(BookDao bookDao) {<!-- -->
        this.bookDao = bookDao;
    }

    public BookServiceImpl() {<!-- -->
        // default constructor body
    }

    @Override
    public void save() {<!-- -->
        System.out.println("BookServiceImpl.......save");
        bookDao. insert();
    }
}

package com.yyz.service.impl;

import com.yyz.service.BookService;

public class BookServiceVip implements BookService {<!-- -->
    @Override
    public void save() {<!-- -->
        System.out.println("BookServiceVip........save");
    }
}

xml file

<?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">
    <!--Create all objects into the IOC container of spring, and give the name id: Indicates the name of the object class: the full class name of the class -->
    <bean id="bookDao" class="com.yyz.dao.impl.BookDaoImpl"/>
    <bean id="bookService" class="com.yyz.service.impl.BookServiceImpl">
        <property name="name" value="Zhang San"></property>
        <property name="age" value="9"></property>
        <property name="bookDao" ref="bookDao"></property>
    </bean>
</beans>

test layer
BookServlet

package com.yyz.servlet;

import com.yyz.service.BookService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BookServlet {<!-- -->
    BookService bookService;

    @Test
    public void add() {<!-- -->
        System.out.println("BookServlet...add");
//1. Get the IOC container
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
//2. Get the object from the container according to the name
        bookService = (BookService) context. getBean("bookService");
        bookService. save();
    }

}

Test Results

Test01

package com.yyz.servlet;

import com.yyz.service.BookService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test01 {<!-- -->
    BookService bookService;
    @Test
    public void test01(){<!-- -->
        ClassPathXmlApplicationContext pathXmlApplicationContext = new ClassPathXmlApplicationContext("spring.xml");
        bookService = (BookService) pathXmlApplicationContext. getBean("bookService");
        bookService. save();
    }
}

Test Results