Java -- essential for interview ☀️ 20000 words to explain the principle of reflection mechanism, Class acquisition method and application scenario ❤️ (recommended Collection) ⭐)

Posted by blinks on Sun, 19 Dec 2021 04:32:01 +0100

📢 Learning background

Little partners learning Java may have heard of Java reflection mechanism, but they are familiar with it and a little strange. This paper mainly focuses on thinking about several questions about Java reflection mechanism often asked in the interview, and then explains it through theoretical knowledge combined with code examples and application scenarios, so as to deepen their cognition and understanding of Java reflection mechanism, and hope to help little partners in need~

🎹 1, What is the Java reflection mechanism?

🎸 1.1 reflection principle

(1) Java Reflection is a dynamic (runtime) ability to access, detect and modify itself in the Java language. Its main function is to dynamically (runtime) obtain the complete structure information of the class & the method of calling the object~
More simply, when a Java program runs (dynamically), it creates a class reflection object and then performs relevant operations on the class, such as:

  • Gets the member variable & assignment of the object
  • Call the method of the object (including construction method, with / without parameters)
  • Determine the class to which the object belongs

PS: but to be honest, it's still a little difficult to understand the official definition directly. Let's talk more popularly~

(2) Generally, when we use a class, we will know the class and what to do with it. We can directly create an object through new instantiation, and then use this object to operate on the class. This belongs to orthomorphism~

(3) Reflection does not know what class to initialize at the beginning and cannot be instantiated and created using new. It is mainly realized through the reflection API provided by JDK. Only when running can we know what class to operate, and can obtain the complete construction of the class and call the corresponding method. This is reflection~

📣 1.2 reflection examples

The code is as follows:

package com.justin.java.lang;

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

/**
 * @program: Jdk1.8 Test
 * @description: Simple call examples of Orthophoto and reflection
 * @author: JustinQin
 * @create: 2021/8/22 13:23
 * @version: v1.0.0
 **/
public class Student {
    private int id;

    public void setId(int id) {
        this.id = id;
    }
    public int getId() {
        return id;
    }

    public static void main(String[] args) throws Exception{
        //1, Orthomorphic call procedure
        Student student = new Student();
        student.setId(1);
        System.out.println("Orthomorphic call procedure Student id:" + student.getId());

        //2, Reflection call procedure
        Class clz = Class.forName("com.justin.java.lang.Student");
        Constructor studentConstructor = clz.getConstructor();
        Object studentObj = studentConstructor.newInstance();
        
        Method setIdMethod = clz.getMethod("setId", int.class);
        setIdMethod.invoke(studentObj, 2);
        Method getIdMethod = clz.getMethod("getId");
        System.out.println("Orthomorphic call procedure Student id:" + getIdMethod.invoke(studentObj));
    }
}

Output results:

Orthomorphic call procedure Student id:1
 Reflection call procedure Student id:2

In the calling process of the above example, you can see the main process of obtaining the reflection object of a class:

  • Gets the Class instance object of the Class
  • Get Constructor object from Class instance object
  • Then get the reflection object of the class according to the newInstance method of the Constructor object

After obtaining the reflection object of the class, you can operate on the class ~ for example, in the above example, the process of calling the method of the class is as follows:

  • Get the Method object of the Class according to the Class instance object
  • Then call the Method of the specific class according to the invoke Method of the Method object

The previous point also mentioned getting the Class instance object of the Class. In the above example, we use Class Forname ("global name of Class") is used to obtain the Class instance object of the Class. In addition to this, there are other two commonly used. I'll explain it later~

🎵 2, Three ways and differences of obtaining Class in Java reflection mechanism?

📀 2.1 several acquisition methods of class

(1) There are three common ways to obtain the java.lang.Class instance object of a class:

  • Via MyClass Class, where MyClass refers to a specific class~~
  • Pass class Forname ("global naming of class"), which is package name + class name
  • Through new myclass() Getclass(), where MyClass refers to a specific class~

(2) Through MyClass.class, the JVM will use the ClassLoader class loader to load the class into memory, but will not do any class initialization and return the java.lang.Class object

(3) It is obtained through Class.forName("global naming of the class"). Similarly, the class will be loaded into memory by the JVM, and the static initialization of the class will be carried out, returning Java Lang.class object

(4) Through new myclass() Getclass(). This method uses new for instantiation, so static initialization and non static initialization will be carried out. The getClass method belongs to the method in the top-level Object class, and any subclass Object can be called. Whichever subclass is called, the Java of that subclass will be returned Lang.class Object

PS: these three methods are finally implemented in the Java. Net of the corresponding class in the JVM heap Lang. class objects belong to the same, that is, the memory address is the same. The result of = = Double equal sign comparison is true because the same ClassLoader is used to load a class during JVM class loading. No matter how many times it is loaded, Java. Class objects are generated to the heap There is always only one lang. class object. Unless the custom class loader destroys the JVM's parental delegation mechanism and makes the same class loaded by different class loaders, the JVM will treat it as two different Java Lang.class object

🔊 2.2 differences between several methods of code demonstration

Create an entity class, and create static code blocks, dynamic code blocks, parametric construction methods and nonparametric construction methods of the class in the entity class respectively, so as to test the differences of several methods and whether the memory addresses are the same~

(1) Entity class:

public class MyClass {
    private static final String staticStr = "Hi";
    private static int staticInt = 2021;
    private String id;

    static {
        System.out.println("Static code block: staticStr=" + staticStr + ",staticInt=" + staticInt);
    }

    {
        System.out.println("Dynamic code block~");
    }

    public MyClass() {
        System.out.println("Nonparametric construction method~");
    }

    public MyClass(String id) {
        System.out.println("Parametric construction method~");
        this.id = id;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "MyClass{" +
                "id='" + id + '\'' +
                '}';
    }
}

(2) Unit test class:
Unit Test the three methods respectively through @ Test annotation, and then unit Test the combination of the three methods~

package com.justin.java.lang;

import org.junit.Test;

/**
 * @program: Jdk1.8Test
 * @description: Java Three common ways to obtain Class instance objects in reflection mechanism and their differences
 * @author: JustinQin
 * @create: 2021/8/22 15:04
 * @version: v1.0.0
 **/
public class MyClassTest {

    @Test
    public void test1() {
        System.out.println("I MyClass.class mode=========");
        Class<?> class1 = MyClass.class;
    }

    @Test
    public void test2() throws ClassNotFoundException {
        System.out.println("II Class.forName mode=========");
        Class class2 = Class.forName("com.justin.java.lang.MyClass");
    }


    @Test
    public void test3() {
        System.out.println("III new MyClass().getClass mode=========");
        Class class3 = new MyClass().getClass();
    }

    @Test
    public void test12() throws ClassNotFoundException {
        System.out.println("I MyClass.class mode=========");
        Class<?> class1 = MyClass.class;
        System.out.println("II Class.forName mode=========");
        Class class2 = Class.forName("com.justin.java.lang.MyClass");
    }

    @Test
    public void test13() {
        System.out.println("I MyClass.class mode=========");
        Class<?> class1 = MyClass.class;
        System.out.println("III new MyClass().getClass mode=========");
        Class class3 = new MyClass().getClass();
    }

    @Test
    public void test23() throws ClassNotFoundException {
        System.out.println("II Class.forName mode=========");
        Class class2 = Class.forName("com.justin.java.lang.MyClass");
        System.out.println("III new MyClass().getClass mode=========");
        Class class3 = new MyClass().getClass();
    }

    @Test
    public void test() throws ClassNotFoundException {
        System.out.println("4, Memory address comparison of three methods=========");
        Class<?> class1 = MyClass.class;
        Class class2 = Class.forName("com.justin.java.lang.MyClass");
        Class class3 = new MyClass().getClass();
        System.out.println("Comparison results=========");
        System.out.println("MyClass.class and Class.forName Whether the memory address comparison is the same:" + (class1 == class2));
        System.out.println("MyClass.class and new MyClass().getClass Whether the memory address comparison is the same:" + (class1 == class3));
        System.out.println("Class.forName and new MyClass().getClass Whether the memory address comparison is the same:" + (class2 == class3));
    }
}

Execute the units one by one, and the test results are as follows:

* test1()method
 I MyClass.class mode=========

*  test2()method
 II Class.forName mode=========
Static code block: staticStr=Hi,staticInt=2021

*  test3()method
 III new MyClass().getClass mode=========
Static code block: staticStr=Hi,staticInt=2021
 Dynamic code block~
Nonparametric construction method~

*  test12()method
 I MyClass.class mode=========
II Class.forName mode=========
Static code block: staticStr=Hi,staticInt=2021

*  test13()method
 I MyClass.class mode=========
III new MyClass().getClass mode=========
Static code block: staticStr=Hi,staticInt=2021
 Dynamic code block~
Nonparametric construction method~

*  test23()method
 II Class.forName mode=========
Static code block: staticStr=Hi,staticInt=2021
 III new MyClass().getClass mode=========
Dynamic code block~
Nonparametric construction method~

*  test()method
 4, Memory address comparison of three methods=========
Static code block: staticStr=Hi,staticInt=2021
 Dynamic code block~
Nonparametric construction method~
Comparison results=========
MyClass.class and Class.forName Whether the memory address comparison is the same: true
MyClass.class and new MyClass().getClass Whether the memory address comparison is the same: true
Class.forName and new MyClass().getClass Whether the memory address comparison is the same: true

Through the test results of test1, test2 and test3, the difference description of the yellow mark in the three methods and differences of 2.1 is verified, namely:

  • MyClass.class does not initialize any classes
  • Class.forName does the static initialization of the class
  • new MyClass(). Both static initialization and non static initialization of getClass will be performed
  • Using any of these three methods, the memory address will be the same when the JVM is loaded into memory

The test results obtained from the combination of test23 show that the static code block will only be loaded once~

After talking so much, in addition to knowing the basic principle and basic use, it is more important to know some practical application scenarios. Let's introduce them next~

💥 3, What are the application scenarios of Java reflection mechanism?

🎶 3.1 application scenarios

  • Simple factory mode optimization in factory mode
  • Implementation of dynamic agent mode in agent mode
  • Java JDBC database operation

🎧 3.2 simple factory mode optimization

📢 3.2. 1 what is the simple factory model?

There are mainly 23 design patterns in Java, of which the factory pattern is one, and the simple factory pattern, as the name suggests, is also one of the factory patterns, but it is relatively simple. The simple factory pattern can also be called the static method pattern (because factory classes generally define a static method internally).
From the perspective of real life, factories are specifically responsible for the production of products. Similarly, in the design mode, the simple factory mode can be understood as a class specifically responsible for the production object, which is called "factory class".

🎹 3.2. 2 what is the use of simple factory mode?

By creating a corresponding factory class, the simple factory mode separates the operation of class instantiation from the operation of using objects, so that users can instantiate the required specific product class without knowing the specific parameters, so as to avoid explicit specification in the client code and realize decoupling. That is, users can directly consume the product without knowing the details of its production~

🎸 3.2. 3 how to realize simple engineering mode?

The core of implementing the simple engineering mode is to create a factory class, define a static method internally, pass in different parameter identifiers, group through switch, and create different subclass objects through new instantiation~

Implementation example:

Step 1: create an abstract product class

public interface Product {
    public abstract void show();
}

Step 2: create a specific product class:

public class ProductA implements Product {
    @Override
    public void show() {
        System.out.println("Produced products A");
    }
}
public class ProductB implements Product {
    @Override
    public void show() {
        System.out.println("Produced products B");
    }
}

public class ProductC implements Product {
    @Override
    public void show() {
        System.out.println("Produced products C");
    }
}

Step 3: create a simple factory class

public class SimpleFactory {
    /**
     * Implement simple factory mode
     * @param pName Product identification
     * @return Return specific products
     */
    public static Product createProduct(String pName){
        switch (pName){
            case "A":
                return new ProductA();
            case "B":
                return new ProductB();
            case "C":
                return new ProductC();
            default:
                return null;
        }
    }
}

Step 4: call the simple factory class

public class SimpleFactoryTest {
    public static void main(String[] args) {
        try {
            SimpleFactory.createProduct("A").show();
        } catch (NullPointerException e) {
            System.out.println("No, A This product cannot be produced~");
        }
        try {
            SimpleFactory.createProduct("B").show();
        } catch (NullPointerException e) {
            System.out.println("No, B This product cannot be produced~");
        }
        try {
            SimpleFactory.createProduct("C").show();
        } catch (NullPointerException e) {
            System.out.println("No, C This product cannot be produced~");
        }
        try {
            SimpleFactory.createProduct("D").show();
        } catch (NullPointerException e) {
            System.out.println("No, D This product cannot be produced~");
        }
    }
}

📣 3.2. 4 simple factory mode optimization

(1) Disadvantages of simple factory model

  • High operation cost: the logic of the factory class must be modified every time a subclass of the interface is added
  • Increased system complexity: logic must be added to the factory class every time a subclass of the interface is added

These two disadvantages from the implementation of the SimpleFactory factory class in the previous example, we can see that the maintenance cost of the factory class SimpleFactory in the simple factory mode is a little high, because the specific product class may be updated very frequently in practice, and the factory class needs to be modified every time. At this time, the Java reflection mechanism can be used to optimize the simple factory mode~

(2) Optimization of simple factory model
The Java reflection mechanism is adopted to dynamically create different subclass object instances by passing in the subclass global naming (package name + class name), so that the factory class can realize the unified creation of subclass instance objects without adding product interface subclasses and modifying the logic of factory class~

(3) Optimization steps of simple factory mode
Step 1: create factory class
The Java reflection mechanism is used to optimize the factory Class, which mainly takes the className, that is, the global naming of the subclass (package name + Class name) as the input parameter, obtains the java.lang.Class instance object of the Class through Class.forName, and then obtains the instance object of the specific subclass through the getInstance method of the Class instance object~

public class Factory {
    public static Product getInstance(String className) {
        Product realProduct = null;
        try {
            Class pClass = Class.forName(className);
            realProduct = (Product) pClass.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return realProduct;
    }
}

Step 2: call the factory class

public class FactoryTest {
    public static void main(String[] args) {
        try {
            Product productA = Factory.getInstance("com.justin.java.lang.ProductA");
            productA.show();
        } catch (NullPointerException e) {
            System.out.println("No, A This product cannot be produced~");
        }

        try {
            Product productB = Factory.getInstance("com.justin.java.lang.ProductB");
            productB.show();
        } catch (NullPointerException e) {
            System.out.println("No, B This product cannot be produced~");
        }

        try {
            Product productC = Factory.getInstance("com.justin.java.lang.ProductC");
            productC.show();
        } catch (NullPointerException e) {
            System.out.println("No, C This product cannot be produced~");
        }

        try {
            Product productD = Factory.getInstance("com.justin.java.lang.ProductD");
            productD.show();
        } catch (Exception e) {
            System.out.println("No, D This product cannot be produced~");
        }


    }
}

Optimization results:

After using the Java reflection mechanism to optimize the simple factory mode, you can see that no matter how frequently the specific product class is updated, there is no need to modify the factory class, which solves the problems of high operation cost and high system complexity of the ordinary simple factory mode~

🎵 3.2. 5. Re optimization of simple factory mode

(1) Optimize the background again

After the factory class of simple factory mode is optimized by Java reflection mechanism, there is still a problem at this time. The global naming (package name + class name) of subclasses is dead, but in fact, it is difficult for developers to predict the global naming (package name + class name) of all subclasses in advance when writing code, so secondary optimization is required~

(2) Optimize the implementation idea again

Through the configuration file method, the global naming corresponding to the class name is uniformly defined (package name + class name), and the configuration file is stored in the resource directory. When the program runs, the global naming of the subclass defined in the configuration file is dynamically obtained through the ClassLoader class loader~

(3) Optimize the implementation steps again

Re optimization step 1: the relevant optimization remains unchanged from the first optimization~

Optimize step 2 again: configure the global naming corresponding to the class name (package name + class name)
Create property profile product properties

//Global naming (package name + class name) definition of relevant subclasses of Product abstract class
ProductA = com.justin.java.lang.ProductA
ProductB = com.justin.java.lang.ProductB
ProductC = com.justin.java.lang.ProductC

Note: put product Properties need to be stored in the src/main/resources resource directory. If the resource directory does not exist, it needs to be created manually~

Optimize step 3 again: modify the calling factory class

public class FactoryTest {
    @Test
    public void test() throws IOException {
        ClassLoader classLoader = this.getClass().getClassLoader();
        Properties prop = new Properties();
        prop.load(classLoader.getResourceAsStream("Product.properties"));

        String className = "";
        try {
            className = prop.getProperty("ProductA");
            Product productA = Factory.getInstance(className);
            productA.show();
        } catch (NullPointerException e) {
            System.out.println("No, A This product cannot be produced~");
        }

        try {
            className = prop.getProperty("ProductB");
            Product productA = Factory.getInstance(className);
            productA.show();
        } catch (NullPointerException e) {
            System.out.println("No, B This product cannot be produced~");
        }

        try {
            className = prop.getProperty("ProductC");
            Product productA = Factory.getInstance(className);
            productA.show();
        } catch (NullPointerException e) {
            System.out.println("No, C This product cannot be produced~");
        }
    }
}

Operation results:

Produced products A
 Produced products B
 Produced products C

📀 3.3 dynamic agent implementation in agent mode

🔊 3.3. 1 what is the agent model?

Proxy mode is a design mode that accesses the target object through the proxy object. It can also expand the proxy object and enhance the function of the target object without modifying the target object~

what? Still don't understand?

More generally speaking, the agency model is to do something (buy a train ticket), buy it yourself (go directly to the railway station), but entrust others to buy it (if you don't have time, you'd better buy it), and let others do other things for you (book a hotel)~

Agent mode is divided into static agent and dynamic agent, which will be introduced next~

💥 3.3. 2 what is a static proxy?

(1) Static proxy is a proxy mode of proxy mode, which requires the proxy object and target object to implement the same interface
(2) The agent class of static agent is the source code written by the programmer. After compilation, the class bytecode file of the agent class can be obtained, that is, the actual class bytecode file of the agent class has been obtained before the program runs

🎶 3.3. 2 what is dynamic agent?

Dynamic agent

(1) Dynamic proxy is also a proxy mode of proxy mode, but only the target object needs to implement the interface, and the proxy object does not need to implement the interface~
(2) There is no class bytecode file for the agent class of dynamic agent after compilation, but the class bytecode file of agent class is dynamically generated by Java reflection mechanism at runtime~

The most commonly used dynamic agents are JDK native dynamic agent and cglib dynamic agent, which will be introduced next~

JDK native dynamic proxy

JDK native dynamic proxy mainly uses the functions of JDK API
java.lang.reflect.Proxy and Java lang.relfect. Invocationhandler is implemented by these two classes~

Through Java lang.reflect. The newProxyInstance method of proxy proxy class passes three parameters:
The loader of the target object passes through MyClass getClass(). Get by getclassloader
The implementation interface type of the target object is through object getClass(). Getinterfaces() method
The invocationhandler event handler instantiates the object through new and overrides the invoke method to obtain

example:

User interface class IUserDao

public interface IUserDao {
    //Add data
    public void insert();
}

Target object class UserDao

/**
 * @program: DataStructures
 * @description:
 * @author: JustinQin
 * @create: 2021/8/23 23:32
 * @version: v1.0.0
 **/
public class UserDao implements IUserDao{

    @Override
    public void insert() {
        System.out.println("Add data");
    }
}

Dynamic proxy class UserProxy

/**
 * @program: Jdk1.8Test
 * @description: Dynamic proxy class
 * @author: JustinQin
 * @create: 2021/8/23 23:31
 * @version: v1.0.0
 **/
public class UserProxy {
    private Object target; //Target object

    public UserProxy(Object target) {
        this.target = target;
    }

    /**
     * Get the proxy object using JDK API
     * @return
     */
    public Object getProxyInstance() {
        //Loader for target object
        ClassLoader loader = target.getClass().getClassLoader();

        //Implementation interface type of the target object
        Class<?>[] interfaces = target.getClass().getInterfaces();

        //Invocationhandler event handler instance object
        InvocationHandler h = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("Before adding data: manually start the transaction");
                // Execute target object method
                Object value = method.invoke(target, args);
                System.out.println("After adding data: manually commit transactions");
                return null;
            }
        };
        //Pass in three parameters, create an instance object of the proxy class, and return
        return Proxy.newProxyInstance(loader, interfaces,h);
    }
}


Dynamic agent unit test class

/**
 * @program: Dynamic agent unit test class
 * @description:
 * @author: JustinQin
 * @create: 2021/8/23 23:42
 * @version: v1.0.0
 **/
public class UserProxyTest {
    @Test
    public void test() {
        IUserDao target = new UserDao();
        System.out.println("Target object information:" + target.getClass());
        //Get proxy class instance object
        IUserDao proxy = (IUserDao) new UserProxy(target).getProxyInstance();
        System.out.println("Proxy object information:" + proxy.getClass());
        //Execution agent method
        proxy.insert();
    }
}

Unit test execution results

Target object information: class com.justin.java.reflect.UserDao
 Proxy object information: class com.sun.proxy.$Proxy2
 Before adding data: manually start the transaction
 Add data
 After adding data: manually commit transactions

cglib dynamic proxy

cglib (Code Generation Library) is a third-party code generation class library, which dynamically generates a subclass object in memory at runtime, so as to expand the function of the target object.

Spring AOP is implemented by combining cglib dynamic proxy and JDK native dynamic proxy. There is no more introduction here. If you are interested, you can refer to the resources to learn~

🎧 3.3. 3 how to use Java reflection mechanism in dynamic proxy?

In the JDK native dynamic proxy, in the process of obtaining the proxy sample object, obtain the Class loader of the target object through target getClass(). Getclassloader () obtains the Class loader of the target object, and the Class instance of the target object is obtained by target.getClass(). The object is implemented by Java reflection mechanism~

📢 3.4 implementation of Java JDBC database operation

🎹 3.4. 1 use reflection to load JDBC Driver

I believe many small partners know that Java JDBC connecting to the database is mainly divided into seven steps. The first step is to load JDBC drivers, and use java reflection mechanism to load drivers of different databases by passing in different driver names~

Class.forName("com.mysql.jdbc.Driver"); //Load MySQL driver
Class.forName("oracle.jdbc.driver.OracleDriver"); //Load Oracle driver

Link: Mysql driver rack package Mysql-connector-java-5.1 30.jar Extraction code: pc63

Link: Oracle driver rack package ojdbc14-10.2 0.4. 0.jar Extraction free code

🎸 3.4.2 Java JDBC connection example

Create test library tables and data

create DATABASE test;
-- DROP TABLE IF EXISTS test.user;
create table test.user(
id int(7) primary key not null auto_increment,
name varchar(255),
sex char(1),
age int(3)
)ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
insert into TEST.user(name,sex,age) values('Zhang Yi','male',21);
insert into TEST.user(name,sex,age) values('Zhang Er','female',22);
insert into TEST.user(name,sex,age) values('Zhang San','male',23);

Seven steps for Java MySQL JDBC connection~

    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1. Load JDBC Driver
        Class.forName("com.mysql.jdbc.Driver");
        //2. Get the Connection object of the database
        Connection connection = DriverManager.getConnection(
                "jdbc:mysql://localhost/test", //mysql connection URL. Test indicates the name of the database you want to connect to
                "root", //Database user name
                "abc@123456"); //password
        //3. Get the PrepareStatement object of the database
        PreparedStatement prepareStatement = connection.prepareStatement("select * from TEST.user where id = ?");
        //4. Set incoming parameters
        prepareStatement.setInt(1, 1);
        //5. Upload the sql statement to the server to execute (extract) and return the result set
        ResultSet result = prepareStatement.executeQuery();
        //6. Process the returned ResultSet result set
        while (result.next()) {
            System.out.print(result.getInt("id") + ",");
            System.out.print(result.getString("name") + ",");
            System.out.print(result.getString("sex") + ",");
            System.out.print(result.getInt("age"));
            System.out.print("\n");
        }
        //7. Release related resources: Connection object, PrepareStatement object and ResultSet object.
        connection.close();
        prepareStatement.close();
        result.close();
    }

Execution result:

1,Zhang Yi,male,21

Seven steps for Java Oracle JDBC connection~

public class JdbcOracleTest {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1. Load JDBC Driver
        Class.forName("oracle.jdbc.driver.OracleDriver");
        //2. Get the Connection object of the database
        Connection connection = DriverManager.getConnection(
                "jdbc:oracle:thin:@127.0.0.1:1521:orcl",	//oracle connection url
                "root", //Database user name
                "abc@123456"); //password
        //3. Get the PrepareStatement object of the database
        PreparedStatement prepareStatement = connection.prepareStatement("select * from TEST.user where id = ?");
        //4. Set incoming parameters
        prepareStatement.setInt(1, 1);
        //5. Upload the sql statement to the server to execute (extract) and return the result set
        ResultSet result = prepareStatement.executeQuery();
        //6. Process the returned ResultSet result set
        while (result.next()) {
            System.out.print(result.getInt("id")+",");
            System.out.print(result.getString("name")+",");
            System.out.print(result.getString("sex")+",");
            System.out.print(result.getInt("age"));
            System.out.print("\n");
        }
        //7. Release related resources: Connection object, PrepareStatement object and ResultSet object.
        connection.close();
        prepareStatement.close();
        result.close();
    }
}

PS: the database is connected and operated through Java JDBC. The connection here is a single connection, directly through drivermanager Getconnection, a Java Native database connection method, is now implemented in the actual Java Spring project by configuring the database connection pool of mybatis. However, the principle is the same. The loading driver also uses the java reflection mechanism to specify different driver names to load different database drivers~

Configuring spring mybatis.com for database connection pool xml

	<!-- be based on tomcat jdbc Data source for connection pool  -->
    <bean id="dataSource" class="com.justin.datasource.TomcatDataSource" init-method="createPool">
		<!-- be based on dbcp Data source for connection pool
		<bean id="dataSource" class="com.justin.datasource.DbcpDataSource" destroy-method="close"> -->
		<!-- Based on Ali druid Data source for connection pool
        <bean id="dataSource" class="com.justin.datasource.DruidDataSource" destroy-method="close"> -->

		<property name="driverClassName" value="${app-data-source.driverClassName}" />
		<property name="url" value="${app-data-source.url}" />
		<property name="username" value="${app-data-source.username}" />
		<property name="password" value="${app-data-source.password}" />
		<!-- Initialize connection size -->
		<property name="initialSize" value="${app-data-source.initialSize}" />
		<!-- Maximum number of connection pools -->
		<property name="maxActive" value="${app-data-source.maxActive}" />
		<!-- Connection pool maximum idle -->
		<property name="maxIdle" value="${app-data-source.maxIdle}" />
		<!-- Connection pool minimum idle -->
		<property name="minIdle" value="${app-data-source.minIdle}" />
		<!-- Gets the maximum connection wait time -->
		<property name="maxWait" value="${app-data-source.maxWait}" />
	</bean>

Database configuration information JDBC propertis

#Database connection driver
app-data-source.driverClassName=com.mysql.jdbc.Driver
#Database connection url
app-data-source.url=jdbc:mysql://localhost:3306/test?useSSL=false&characterEncoding=UTF-8
#Database user
app-data-source.username=root
#Database user password (encrypted)
app-data-source.password=abc@123456
#Connection pool initialization size
app-data-source.initialSize=10
#Maximum number of connection pools
app-data-source.maxActive=50
#Connection pool maximum idle
app-data-source.maxIdle=20
#Connection pool minimum idle
app-data-source.minIdle=5
#Gets the maximum connection wait time
app-data-source.maxWait=30000

Interview summary

1, What is the Java reflection mechanism?
1. Java Reflection is a dynamic (runtime) ability to access, detect and modify itself in the Java language. Its main function is to dynamically (runtime) obtain the complete structure information of the class & the method of calling the object~
More simply, when a Java program runs (dynamically), it creates a class reflection object and then performs relevant operations on the class, such as:

  • Gets the member variable & assignment of the object
  • Call the method of the object (including construction method, with / without parameters)
  • Determine the class to which the object belongs

2. More generally, when we use a class, we will know the class and what to do with it. We can directly create an object through new instantiation, and then use this object to operate on the class. This belongs to orthomorphism~

3. Reflection does not know what class to initialize at the beginning and cannot be instantiated and created using new. It is mainly realized through the reflection API provided by JDK. Only when running can we know what class to operate, and can obtain the complete construction of the class and call the corresponding method. This is reflection~

2, Three ways and differences of obtaining Class in Java reflection mechanism?
1. Get the Java. XML of the class Lang.class instance object. There are three common methods:

  • Via MyClass Class get
  • Pass class Forname ("global naming of class") gets
  • Through new myclass() Getclass() get

2. Via MyClass Class, the JVM will use the ClassLoader class loader to load the class into memory, but will not do any class initialization and return Java Lang.class object

3. Pass class Forname ("global naming of the class"). Similarly, the class will be loaded into memory by the JVM, and the static initialization of the class will be carried out, returning Java Lang.class object

4. Through new myclass() Getclass(). This method uses new for instantiation, so = = static initialization and non static initialization will be performed = =. The getClass method belongs to the method in the top-level Object class, and any subclass Object can be called. Whichever subclass is called, the Java of that subclass will be returned Lang.class Object

5. These three methods are finally implemented in the Java. Java of the corresponding class in the JVM heap Lang. class objects belong to the same, that is, the memory address is the same. The result of = = Double equal sign comparison is true because the same ClassLoader is used to load a class during JVM class loading. No matter how many times it is loaded, Java. Class objects are generated to the heap There is always only one lang. class object. Unless the custom class loader destroys the JVM's parental delegation mechanism and makes the same class loaded by different class loaders, the JVM will treat it as two different Java Lang.class object

3, What are the application scenarios of Java reflection mechanism?

  • Simple factory mode optimization in factory mode
  • Implementation of dynamic agent mode in agent mode
  • Java JDBC database operation

It's not easy to be original. If you think it's useful, let's click three times (like + collection + comments) + pay attention and support. Thank you very much~

Topics: Java