Java reflection mechanism

  • Frame = annotation + reflection + design pattern

Overview of Java reflection mechanism

Java Reflection

  • Reflection is considered the key to a dynamic language. Reflection allows programs to use the Reflection API to retrieve the internal information of any class at runtime and to directly manipulate the internal properties and methods of any object

  • After the Class is loaded, an object of Class type is generated in the method area of the heap memory (each Class has only one Class object). This object contains the complete structure of the Class. We can see the structure of the class through this object; This object is like a mirror through which you can see the structure of the class, so we call it a reflection

  • Normal mode: Import the required package class name -> Instantiate by New -> Get the instantiated object

  • Reflection: Instantiate the object -> getClass() method -> get the full “package class” name

Research and Application of Java reflection mechanism

Functionality provided by the Java reflection mechanism

  • Determine the class to which any object belongs at run time
  • Constructs an object of any class at run time
  • Determine which member variables and methods any class has at run time
  • Get generic information at run time
  • Call the member variables and methods of any object at run time
  • Annotations are processed at run time
  • Generating dynamic proxies

The main API for reflection

  • Java.lang. Class: represents a Class;Source of reflection
  • Java.lang.reflect. Method: Represents the Method of a class
  • Java.lang.reflect. Field: Represents a member variable of the class
  • Java. Lang. Reflect. Constructor: on behalf of the Constructor of a class
  • . .

Example:

package com.atguigu.java;

import org.junit.Test;

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

/ * * *@author lv
 * @createThe 2021-03-01 young * * /
public class ReflectionTest {
    /** * What you can do with the Person class */ before you learn reflection
    @Test
    public void test1 (a) {
// 1. Create an object of the Person class
        Person p1 = new Person("Tom".11);
// 2. Call the internal properties and methods of the object
        p1.age = 18;
        System.out.println(p1.toString());
        p1.show();

        /** * Outside of the Person class, internal private structures such as name, showNation(), private constructor */ cannot be called through the Person class object

    }
    /** * After learning reflection, for the Person class operation */
    @Test
    public void test2 (a) throws Exception {

        Class pClass = Person.class;
// 1. Create class objects by reflection
        Constructor pCons = pClass.getConstructor(String.class, int.class);
        Object pObj = pCons.newInstance("Tom".12);
        System.out.println(pObj.toString()); // Person{name='Tom', age=12}
        Person p1 = (Person) pObj;
// 2. Call the object's automatic properties and methods through reflection
// Call properties:
        Field age = pClass.getDeclaredField("age");
        age.set(p1, 10);
        System.out.println(p1.toString()); // Person{name='Tom', age=10}

// Call method:
        Method show = pClass.getDeclaredMethod("show");
        show.invoke(p1); // I am a person

        /** * Private structures of the Person class can be called by reflection: properties, methods, constructors... * Summary: Reflection can do the same things as class objects, and it can do things that classes and objects cannot do * */
// Call the private constructor
        Constructor pCons1 = pClass.getDeclaredConstructor(String.class);
        pCons1.setAccessible(true);
        Object pObj1 = pCons1.newInstance("Rolay");
        Person p2 = (Person)pObj1;
        Field age2 = pClass.getDeclaredField("age");
        age2.set(p2, 13);
        System.out.println(p2); // Person{name='Rolay', age=13}
// Modify private attributes
        Field name2 = pClass.getDeclaredField("name");
        name2.setAccessible(true);
        name2.set(p2, "Tom2");
        System.out.println(p2); // Person{name='Tom2', age=13}
// Call private methods
        Method showNation = pClass.getDeclaredMethod("showNation", String.class);
        showNation.setAccessible(true);
        String china = (String)showNation.invoke(p2, "China");
        System.out.println("nation: " + china); // nation: China
// System.out.println(p2);}}Copy the code

doubt

  1. Common constructs can be called either by direct new or reflection, whichever is used in development

    • Suggest the direct new approach
    • When to use reflection: When not sure what kind of object to create before compilation
  2. Is reflection contradictory to encapsulation in object orientation, and how do you view these two technical reflections

    • There is no contradiction between the two technologies
    • Encapsulation means that users are advised to use common properties, methods… You are not advised to use private properties, methods…
    • Reflection is saying, what can reflection do

Understand the Class Class and get the Class instance *

Understand Classl class

  1. Class loading process:

The program will generate the corresponding bytecode file (xxx.class) for the specific class after the javac.exe command.

Then we use the java.exe command to interpret a bytecode file. Equivalent to loading a bytecode file into memory, this process is called class loading. A Class loaded into memory is called a runtime Class, and this runtime Class acts as an instance of Class.

  1. In other words, an instance of Class corresponds to a runtime Class

  2. Runtime classes loaded into memory are cached for a period of time; During this time, we can get this runtime class in different ways

Getting a Class instance

The class itself is an object: the perception that everything is an object


    /** ** Understanding the java.lang.Class Class ** 1. Class loading process: * * program after the javac.exe command will generate the specific class corresponding bytecode file (xxx.class). * * Then we use the java.exe command to interpret a bytecode file. Equivalent to loading a bytecode file into memory, * * this process is called class loading. * * A Class loaded into memory is called a runtime Class, and this runtime Class acts as an instance of Class. * * * * 2. In other words, an instance of Class corresponds to a runtime Class * * 3. Runtime classes loaded into memory are cached for a period of time; During this time, * * we can get the runtime class */ in different ways
    @Test
    public void test3 (a) {
// How to get an instance of Class

// Method one: invoke the properties of the runtime class
        Class clazz1 = Person.class;
        System.out.println(clazz1); // The com.atguigu.java.person class itself
// Call getClass() from the object of the runtime class.
        Person p1 = new Person();
        Class clazz2 = p1.getClass();
        System.out.println(clazz2);
// Method three (this method better reflects the dynamic, higher frequency of use) :
// Call the static method of Class: forName(String classPath)
        Class clazz3 = null;
        try {
            clazz3 = Class.forName("com.atguigu.java.Person");
            System.out.println(clazz3);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

// Use the ClassLoader.
        ClassLoader cl = ReflectionTest.class.getClassLoader();
        Class clazz4 = null;
        try {
            clazz4 = cl.loadClass("com.atguigu.java.Person");
            System.out.println(clazz4 == clazz2); // true
        } catch(ClassNotFoundException e) { e.printStackTrace(); }}Copy the code

What types can have Class objects

  • Class: External class, member (inner class, static inner class), local inner class, anonymous inner class
  • Interface: the interface
  • [] : array
  • Enum: enumeration
  • Annotation: @interface
  • Primitive Type: Primitive data type
  • void

Class loading and the understanding of ClassLoader

Understand the loading process of a class

When a program actively uses a class that has not been loaded into memory, the system initializes the class through the following three steps

Class Load

  • Read the class file into memory and create a java.lang. class object for it; This process is done by the class loader

  • Load: Load the bytecode content of the class file into memory, convert this static data into the runtime data structure of the method area, and then generate a java.lang. class object representing this class as an access point (reference address) for the class data in the method area. All the Class data that needs to be accessed and used can only be accessed through this Class object; This loading process requires the participation of the class loader

Class Link (Link)

  • Merges the binary data of the class into the JRE

  • Linking: The process of merging the binaries of Java classes into the JVM’s running state

    1. Validation: Ensure that the loaded class information complies with the JVM specification, such as starting with CAFE, and there are no security concerns
    2. Preparation: Formally allocate memory for class variables (static)Sets the default initial value of a class variableThis memory will be allocated in the method area
    3. Resolution: The process of replacing symbolic references (constant names) in the virtual machine constant pool with direct references (addresses)

Class Initialize

  • The JVM is responsible for initializing classes

  • Initialization:

    1. performClass constructor \<clinit>()Process of method;The class constructor \<clinit>() method is generated by combining the assignment of all class variables in the class that are automatically collected at compile time with statements in the static code block;(Class constructors build class information, not objects of that class.)
    2. When initializing a class, if the parent class is not initialized, the initialization of the parent class must be triggered first
    3. The virtual machine ensures that a class’s

      () methods are locked and synchronized correctly in a multithreaded environment
class A {
	// Code blocks and display assignments are executed in written order
	static {
    	m = 300;
    }
    static int m = 100;
}
// Step 1: load
// step 2: m = 0 after the link ends
// Step 3: After initialization, the value of m is determined by the 
      
       () method
      
// The class constructor of A 
      
       () is generated by the sequential combination of the assignment of class variables and statements in the static code block, similar to
      
// <clinit>() {
// m = 300;
// m = 100;
// }

Copy the code

Class loader

Class loaders are used for:

  • Class loading is used to load the bytecode content of the class file into memory and place this static dataRuntime data structures converted to method areas, and then generate a java.lang.Class object representing the Class in the heap as an access point to the Class data in the method area
  • Class caching: The standard JavaSE class loader can look up classes on demand, but once a class is loaded into the class loader, it stays loaded (cached) for a while; However, the JVM garbage collection mechanism can reclaim these Class objects

Understand: this

Class loaders are used to load classes into memory. The JVM specification defines loaders for the following types of classes

Bootstap ClassLoader

Written in C++, is JVM own class loader, responsible for the Java platform core library, used to load the core class library; The loader is not available directly

Extention ClassLoader

Package the jar packages in the jre/lib/ext directory or the jar packages in the _D java.ext.dirs directory into the working library

System ClassLoader

The most common loader is responsible for packing classes and jars in the java-classpath or _D java.class.path directory

package com.atguigu.java;

import org.junit.Test;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/ * * *@author lv
 * @createThe 2021-03-03 young * /
public class ClassLoaderTest {
    @Test
    public void test1 (a) {
// Custom classes use the system class loader
        ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
        System.out.println("System class loader:" + classLoader); // System classloader: sun.misc.Launcher$AppClassLoader@18b4aac2
// Get the extension classloader from getParent() of the system classloader
        ClassLoader classLoader1 = classLoader.getParent();
        System.out.println("Extended class loader:" + classLoader1); // Extended class loader: sun.misc.Launcher$ExtClassLoader@452b3a41
// Cannot get the boot class loader directly
        ClassLoader classLoader2 = classLoader1.getParent();
        System.out.println("Bootstrap classloader:" + classLoader2); // Bootloader: null, cannot be obtained directly

// Get the boot classloader from String
        ClassLoader classLoader3 = String.class.getClassLoader();
        System.out.println("Bootstrap classloader:" + classLoader3); // Boot class loader: null

    }

    /**
     * 掌握:
     * 集合 Propertise:用来读取配置文件
     *
     */
    @Test
    public void test2 (a) {
// Properties key values are all String
        Properties pros = new Properties();
// FileInputStream fis = null;
        try {
// Read the configuration file in the first way
// jdbc.properties By default, the file is under the current Module
// fis = new FileInputStream("jdbc1.properties");
// fis = new FileInputStream("src\\jdbc.properties");
// pros.load(fis);
// Read the configuration file in the second way
            ClassLoader cl = ClassLoaderTest.class.getClassLoader();
// The getResourceAsStream() method identifies the path under SRC of the current Module by default
            InputStream is = cl.getResourceAsStream("jdbc1.properties");
            pros.load(is);


            String user = pros.getProperty("user");
            String password = pros.getProperty("password");
            System.out.println("user:" + user + "Password." + password);
            // user: no more than password: abc123
            // user: no more than 1 password: abc123

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
// try {
// if (null == fis)
// fis.close();
// } catch (IOException e) {
// e.printStackTrace();
/ /}}}}Copy the code

Create an object * for the runtime class

package com.atguigu.java;

import org.junit.Test;

import java.util.Random;

/ * * *@author lv
 * @create 2021-03-06 9:56
 *
 *
 */
public class ReflectionNewInstanceTest {

    /** * Feel the dynamics of reflection: the framework uses a lot of reflection dynamics, most importantly */
    @Test
    public void test1 (a) {
        int i = new Random().nextInt(3);// 0, 1, 2
        String classPath = "";
        switch (i) {
            case 0:
                classPath = "java.util.Date";
                break;
            case 1:
                classPath = "java.lang.Object";
                break;
            case 2:
                classPath = "com.atguigu.java.Person";
                break;
        }
        Object instance = getInstance(classPath);
        System.out.println(instance);
    }

    /** * creates an object of the specified class *@param classPath
     * @return* /
    public Object getInstance (String classPath) {
        Class clazz = null;
        try {
            clazz = Class.forName(classPath);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Object o = null;
        try {
             o = clazz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } finally {
            returno; }}/** * Creates the object of the corresponding runtime class */ by reflection

    @Test
    public void test (a) {

        Class clazz = Person.class;
        /** * newInstance() : calls this method to create an object of the corresponding runtime class ** This method calls the empty argument constructor of the runtime class ** To create an object of the runtime class normally, the requirements are: * 1. The runtime class must provide an empty parameter constructor * 2. Access to the empty parameter constructor needs to comply with the regulations, usually set to public * * in javabeans, a public empty parameter constructor is required for the following reasons: * 1. 2. When super() is used by default, the parent class is guaranteed to have the constructor * */ when it is convenient for subclasses to inherit the runtime class
        Person obj;
        {
            try {
                obj = (Person)clazz.newInstance();
            } catch (InstantiationException e) {
// Class constructor problem
                e.printStackTrace();
            } catch (IllegalAccessException e) {
// Access problemse.printStackTrace(); }}}}Copy the code

Gets the complete structure of the runtime class

package com.atguigu.java1;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;

/ * * *@author lv
 * @createThe 2021-03-06 11:08 * /
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String value(a) default "hello";
}

package com.atguigu.java1;

/ * * *@author lv
 * @createThe 2021-03-06 10:56 * /
public interface MyInterface {
    void info(a);
}

package com.atguigu.java1;

import java.io.Serializable;

/ * * *@author lv
 * @createThe 2021-03-06 10:53 * /
public class Creature<T> implements Serializable {

    private char gender;
    public double weight;

    private void breath (a) {
        System.out.println("breath");
    }
    public void eat (a) {
        System.out.println("eat"); }}package com.atguigu.java1;

/ * * *@author lv
 * @createWilt thou * / 2021-03-06
@MyAnnotation(value = "hi")
public class Person extends Creature<String> implements Comparable<String>, MyInterface {

    private String name;
    int age;
    public int id;

    public Person (a) {}
    @MyAnnotation(value = "cons")
    private Person (String name) {
        this.name = name;
    }
    Person (String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String display (String interests) {
        return interests;
    }
    @MyAnnotation
    private String show (String nation) {
        System.out.println("Nation:" + nation);
        return nation;
    }

    @Override
    public int compareTo(String o) {
        return 0;
    }

    @Override
    public void info(a) {
        System.out.println("person"); }}Copy the code

Get attribute information based on the above classes

package com.atguigu.java2;

import com.atguigu.java1.Person;
import org.junit.Test;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

/ * * *@author lv
 * @create2021-03-06 11:13 * * Gets the property structure of the current runtime class * */
public class FieldTest {

    @Test
    public void test (a) {
        Class clazz = Person.class;
// Get the attribute structure
        /** * getFields() : Gets the property */ declared as public in the current runtime class and its parent
        Field[] fields = clazz.getFields();
        for (Field f : fields) {
            System.out.println("The Field." + f);
            / * * * Field: public int. Com atguigu. Java1. Person. Id * Field: public double com. Atguigu. Java1. Creature. Weight * /
        }
        System.out.println();
        /** * getDeclaredFields() : gets only all properties declared by the current runtime class itself */
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field f : declaredFields) {
            System.out.println("The Field." + f);
            / * * * Field: private Java lang. String com. Atguigu. Java1. Person. Name * Field: int. Com atguigu. Java1. Person. Age * Field: public int com.atguigu.java1.Person.id */}}/** * Attribute basic information */
    @Test
    public void test2 (a) {
        Class clazz = Person.class;
        Field[] dFields = clazz.getDeclaredFields();
        for (Field f : dFields) {
// 1. Permission modifier
            int modifiers = f.getModifiers();
            System.out.print(Modifier.toString(modifiers) + "\t"); // private, public
// 2. Data type
            Class type = f.getType();
            System.out.print(type + "\t"); // class java.lang.String, int, int
// 3. Variable name
            String name = f.getName();
            System.out.println(name); // name, age, id}}}Copy the code

Get method information based on the above classes

package com.atguigu.java2;

import com.atguigu.java1.Person;
import org.junit.Test;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/ * * *@author lv
 * @create* * Get the method structure of the runtime class */
public class MethodTest {
    @Test
    public void test (a) {
        Class clazz = Person.class;
        /** * getMethods() : Only get the current runtime class and its parent classes with public permission */
        Method[] methods = clazz.getMethods();
        for (Method m : methods) {
            System.out.println(m);
        }
        System.out.println();
        /** * getDeclaredMethods() : Gets all methods declared by the current runtime class itself */
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method m : declaredMethods) {
            System.out.println(m);
        }

        Object o = null;
        try {
            o = clazz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        Method declaredMethod = null;
        try {
            declaredMethod = clazz.getMethod("display", String.class);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        try {
            Object lve = declaredMethod.invoke(o, "lve");
            System.out.println(lve); // lve
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch(InvocationTargetException e) { e.printStackTrace(); }}/** * The exact structure of the method **@Xxxx* * Permission modifier, return value type, method name (parameter type 1 parameter name 1...) throws XxxException {} */
    @Test
    public void test1 (a) {
        Class<Person> clazz = Person.class;
        Method[] methods = clazz.getDeclaredMethods();
        for (Method m : methods) {
// 1. Get the annotation of the method declaration
            Annotation[] annotations = m.getAnnotations();
            for (Annotation anno : annotations) {
                System.out.print(anno);
            }
            System.out.println();
// 2. Permission modifier
            int modifiers = m.getModifiers();
            System.out.print(Modifier.toString(modifiers) + "\t");
// 3. Get the return value typeClass<? > returnType = m.getReturnType(); System.out.print(returnType +"\t");

// TypeVariable
      
       [] typeParameters = m.getTypeParameters();
      
// 4. Get method name
            String name = m.getName();
            System.out.print(name);
// System.out.println();
// System.out.println(typeParameters);
// 5. Get the parameter typeClass<? >[] parameterTypes = m.getParameterTypes(); System.out.print("(");
            if (null! = parameterTypes &&0! = parameterTypes.length) {for (Class c : parameterTypes) {
                    System.out.print(c);
                }
            }
            System.out.print(")");
// 6. The exception thrownClass<? >[] et = m.getExceptionTypes();if (0! = et.length &&null! = et) { System.out.println(" throws ");
                for (int i = 0; i < et.length; i++) {
                    if (i == et.length - 1) {
                        System.out.print(et[i] + "{}");
                    } else {
                        System.out.print(et[i] + ",");
                    }
                    
                }
                System.out.println();
            }
            System.out.println("* * * * * * * * * * * * * * * * * *"); }}}Copy the code

Get additional class structure information

package com.atguigu.java2;

import com.atguigu.java1.Person;
import org.junit.Test;

import java.lang.annotation.Annotation;
import java.lang.reflect.*;

/ * * *@author lv
 * @createThe 2021-03-06 is better * /
public class OtherTest {
    /** * get the constructor structure ** /
    @Test
    public void test (a) {
        Class<Person> clazz = Person.class;
        /** * getConstructors() : Gets the constructor */ whose permission is declared public in the current runtime classConstructor<? >[] constructors = clazz.getConstructors();for (Constructor c : constructors) {
            System.out.println(c);
        }
        System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -"); Constructor<? >[] dCons =null;
        /** * getDeclaredConstructors() : Gets all constructors declared in the current runtime class */
        dCons = clazz.getDeclaredConstructors();
        for (Constructor c : dCons) {
            System.out.println(c);

            intmodifiers = c.getModifiers(); String s = Modifier.toString(modifiers); System.out.println(s); }}/** * Gets the parent of the runtime class */
    @Test
    public void test1 (a) {
        Class<Person> clazz = Person.class;
        /** * getSuperclass() : Gets the parent of the current runtime class */
        Class sClazz = clazz.getSuperclass();
        System.out.println(sClazz); // class com.atguigu.java1.Creature
        Field[] dFields = sClazz.getDeclaredFields();
        for(Field f : dFields) { System.out.println(f); }}/** * Get the generic parent of the runtime class: logical code vs. functional code */
    @Test
    public void test2 (a) {
        Class<Person> clazz = Person.class;
        /** * getGenericSuperclass() : Gets the generic parent of the current runtime class */
        Type genericSuperclass = clazz.getGenericSuperclass();
        System.out.println(genericSuperclass); // com.atguigu.java1.Creature<java.lang.String>
        String typeName = genericSuperclass.getTypeName();
        System.out.println(typeName); // com.atguigu.java1.Creature<java.lang.String>

// Important: Get the generics of the parent with generics ****
        ParameterizedType paramType = (ParameterizedType) genericSuperclass;
GetActualTypeArguments () : Gets the generic type
        Type[] actualTypeArguments = paramType.getActualTypeArguments();
        for (Type t : actualTypeArguments) {
            System.out.println(t.getTypeName());
            // java.lang.String}}/** * get the interface implemented by the runtime class *** * application: dynamic proxy ** /
    @Test
    public void test3 (a) {
        Class clazz = Person.class;
        Class[] interfaces = clazz.getInterfaces();
        for (Class c : interfaces) {
            System.out.println(c);
            /** * interface java.lang.Comparable * interface com.atguigu.java1.MyInterface */
        }
// Gets the interface implemented by the parent of the runtime class
        Class superclass = clazz.getSuperclass();
        Class[] interfaces1 = superclass.getInterfaces();
        for (Class c : interfaces1) {
            System.out.println(c);
            /** * interface java.io.Serializable */}}/** * gets the package in which the current runtime class resides */
    @Test
    public void test4 (a) {
        Class clazz = Person.class;
        Package aPackage = clazz.getPackage();
        System.out.println(aPackage); // package com.atguigu.java1
        String name = aPackage.getName();
        System.out.println(name); // com.atguigu.java1
    }
    /** * get the annotation of the runtime class ***** * application: the framework uses ** /
    @Test
    public void test5 (a) {
        Class clazz = Person.class;
        Annotation[] clazzAnnotations = clazz.getAnnotations();
        for (Annotation a : clazzAnnotations) {
            System.out.println(a);
// System.out.println(a.toString());
            / * * *@com.atguigu.java1.MyAnnotation(value=hi)
             */}}}Copy the code

Invoke the specified structure * of the runtime class

Properties of * * *

  • getField()
  • GetDeclaredField () – to master
  • SetAccessible () – to master
package com.atguigu.java2;

import com.atguigu.java1.Person;
import org.junit.Test;

import java.lang.reflect.Field;

/ * * *@author lv
 * @create* * Get the specified structure of the runtime class by reflection: properties, methods, constructors * */
public class ReflectionConsTest {
    /** * Understand how to get attributes -- understand how to get attribute structures */
    @Test
    public void testField (a) {
        Class clazz = Person.class;
// Create an object for the runtime class
        Person p1 = null;
        try {
            p1 = (Person) clazz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        /** * getField() : getField() : getField() : getField() : getField()
        try {
            Field id = clazz.getField("id");
            /** * Set (instance, value) */
            id.set(p1, 123);
            /** * get(instance) */
// Object o = id.get(p1);
            int i = (int) id.get(p1);
            System.out.println(i); / / 123

        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch(IllegalAccessException e) { e.printStackTrace(); }}/** * need to master this method to obtain attributes -- master */
    @Test
    public void testField1 (a) {
        Class clazz = Person.class;
        Person p1 = null;
        try {
            p1 = (Person) clazz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        /** * getDeclaredField() : This method is usually used to get the property */
        try {
// Field age = clazz.getDeclaredField("age");
// age.set(p1, 10); // IllegalAccessException: illegal access
            Field name = clazz.getDeclaredField("name");
            /** * setAccessible(Boolean) : This property can be modified when the permission is not public
            name.setAccessible(true);
            name.set(p1, "Tomer");
            String nameStr = (String) name.get(p1);
            System.out.println(nameStr); // Tomer

        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
// IllegalAccessException: illegal accesse.printStackTrace(); }}}Copy the code

Methods * * * *

  • getDeclaredMethod(methodName, args…)
  • setAccessible(boolean)
  • invoke(instance, args..) / invoke(clazz, args..)
/** * operates on methods specified in the runtime class -- master */
    @Test
    public void testMethod (a) {
        Class clazz = Person.class;
        Person p1 = null;
        try {
            p1 = (Person) clazz.newInstance();
            /** * 1.getDeclaredMethod(methodName, args...) SetAccessible (true) : Ensures that the method is callable. 3. Invoke (instance, args...) Call this method */
            Method show = clazz.getDeclaredMethod("show", String.class);
            show.setAccessible(true); // Error: IllegalAccessException if this method is not set
            String china = (String) show.invoke(p1, "China");
            System.out.println(china);

            System.out.println("******************* How to call static methods ********************");

// private static void showInfo ()
            Method showInfo = clazz.getDeclaredMethod("showInfo");
            showInfo.setAccessible(true);
// Null is returned by default if the method called in the runtime class returns no value
            Object invoke = showInfo.invoke(clazz);
// Object invoke = showInfo.invoke(null); // Write arguments to null

            System.out.println("invoke:" + invoke); / / invoke: null


        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch(InvocationTargetException e) { e.printStackTrace(); }}Copy the code

The constructor * * *

/** * calls the constructor specified in the runtime class -- learn about ** /
    @Test
    public void testCons (a) {

        Class clazz = Person.class;
        Constructor dCons = null;
        try {
            GetDeclaredConstructor (argsClass...); : gets the constructor */ for the specified argument
// private Person (String name)
            dCons = clazz.getDeclaredConstructor(String.class);
// 2. setAccessible(true) : indicates that the constructor is accessible
            dCons.setAccessible(true);
// 3. The constructor calls newInstance() to create objects for the runtime class
            Person p2 = (Person) dCons.newInstance("Jerry");
            System.out.println(p2);

        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch(InvocationTargetException e) { e.printStackTrace(); }}Copy the code

The Application of Reflection: Dynamic Proxies (Dynamic)

Principle of proxy pattern

Wrap the object with a proxy and replace the original object with that proxy object; Any calls to the original object go through the proxy; The proxy object determines if and when a method call is rolled over to the original object

  • The operation of proxy mechanism, which belongs to static proxy, is characterized by the proxy class and the target object class are determined during compilation, which is not conducive to the scalability and flexibility of the program. At the same time, each proxy class can only serve one interface, so the program development is bound to produce too many proxies; It is best to use a single proxy class for all proxy functionality.

  • A dynamic proxy is a proxy object that a client calls other objects through a proxy class and creates the target class dynamically when the program is running

  • Dynamic proxy applications:

    • debugging
    • Remote method call
  • Advantages of dynamic proxy over static proxy:

    1. All methods declared in the abstract role (interface) are moved to a centralized method in the calling handler (A proxy class can handle all other proxy classesIn this way, we can deal with multiple methods more flexibly and uniformly

The instance

package com.atguigu.java;

/ * * *@author lv
 * @create* * Static proxy examples * Specific: Proxy classes and proxied classes are determined at compile time
interface ClothFactory {
    void produceCloth(a);
}

/** * proxy class ** /
class ProxyClothPactory implements ClothFactory {

    private ClothFactory factory;
    public ProxyClothPactory (ClothFactory factory) {
        this.factory = factory;
    }
    @Override
    public void produceCloth(a) {
        System.out.println("Agent factory to do some preparation: produceCloth");
        factory.produceCloth();
        System.out.println("Finished some finishing touches for the factory"); }}/** * proxy class ** /
class NikeClothFactory implements ClothFactory {

    @Override
    public void produceCloth(a) {
        System.out.println("Nike factory starts making clothes."); }}public class StaticProxyTest {
    public static void main(String[] args) {

// Create an object of the proxied class
        NikeClothFactory nikeClothFactory = new NikeClothFactory();
// Create objects of the proxy class
        ProxyClothPactory proxyClothPactory = newProxyClothPactory(nikeClothFactory); proxyClothPactory.produceCloth(); }}package com.atguigu.java;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/** * proxy: interface + proxy class + dynamic proxy class **@author lv
 * @create* * Example of dynamic proxy * */

interface Human {
    String getBelief (a);
    void eat (String food);
}

class HumanUtil {
    public void method1 (a) {
        System.out.println("----------------method1-----------------");
    }
    public void method2 (a) {
        System.out.println("----------------method2-----------------"); }}// Proxy class
class SuperMan implements Human {

    @Override
    public String getBelief(a) {
        return "I believe I can Fly!";
    }

    @Override
    public void eat(String food) {
        System.out.println("eat:"+ food); }}/** * To implement dynamic proxy, you need to solve the following problems: * 1. How to dynamically create a proxy class and its object from the proxy class loaded in memory * 2. How to dynamically call a proxied class method */ when calling a method from a proxied class object

class ProxyFactory {

// Call this method and return an object of the proxy class; Solving problem 1
    public static Object getProxyInstance (Object obj) { // obj proxied object

        MyInvocationHandler handler = new MyInvocationHandler();
        handler.bind(obj);
// The invoke() method is automatically invoked after the following code is executed
        returnProxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler); }}// Solve problem 2
class MyInvocationHandler implements InvocationHandler {

    private Object obj; // Assign using the object of the proxied class

    public void bind (Object obj) {
        this.obj = obj;
    }


// Invoke () when we invoke method A via an object of the proxy class: invoke()
// The function of method A to be executed by the proxied class is declared in invoke()
    @Override
    /** * proxy: object of the proxy class * method: method called by the proxy class */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    	// Section-oriented examples
        HumanUtil humanUtil = new HumanUtil();
        humanUtil.method1();
        /** * method: the method called by the proxied object. This method is also called by the proxied object
        Object returnValue = method.invoke(obj, args);
    	// Section-oriented examples
        humanUtil.method2();
        
        returnreturnValue; }}public class DynamicProxyTest {
    public static void main(String[] args) {
        SuperMan superMan = new SuperMan();

// proxyInstance: object of the proxy class
// Object proxyInstance = ProxyFactory.getProxyInstance(superMan);
        Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);

// When a method is called from proxyInstance, the method of the same name in the proxied class is automatically called
        String belief = proxyInstance.getBelief();
        System.out.println("Are." + belief); // belief: I believe I can Fly!
        proxyInstance.eat("Green vegetables"); // Eat: Green vegetables

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

        NikeClothFactory nikeClothFactory = new NikeClothFactory();

// Object proxyClothFactory = ProxyFactory.getProxyInstance(nikeClothFactory);
        ClothFactory proxyClothFactory = (ClothFactory) ProxyFactory.getProxyInstance(nikeClothFactory);
// The corresponding properties and methods can be called only after being strong-pressed
        proxyClothFactory.produceCloth(); // Nike factory starts to produce clothing}}Copy the code

Dynamic Proxy and AOP (Aspect Orient Programming)

  • See the example code – HumanUtil above for details

The problem

Write out three common ways to get an instance of a Class

// Method 1: Understand
// This method is dead at compile time and cannot be dynamic
Class clazz = Person.class;

// Method two: familiarity
Person p1 = new Person();
Class clazz = p1.getClass();

// Method three: -- Master
// This method reflects the dynamic nature of reflection and loads the specified class at runtime
String classPath = "xxx/xxx/Xxx";
Class clazz = Class.forName(classPath);
Copy the code

Talk about understanding the Class Class

  • Class is a Class
  • A Class instance corresponds to a runtime Class (Class, array, interface) loaded into memory
  • The structure of the runtime Class can be invoked from an instance of the Class Class

Common method of creating objects corresponding to the runtime Class, code implementation; This operation requires conditions that the runtime class constructor needs to meet

Class clazz = Class.forName(String classPath);
Object obj = clazz.newInstance();
Method show = clazz.getDeclaredMethod("show", String.class);
show.setAccessiable(true);
show.invoke(obj, "China");
Copy the code
  1. The null-parameter constructor must be used
  2. The constructor must have sufficient permissions, usually written public

In the project module SRC configuration file named “jdbc.properties”, the content of the file is: name=Tom; How to get the variable “Tom” in the program by code

public class ClassLoaderTest {

    @Test
    public void test2 (a) {
// Properties key values are all String
        Properties pros = new Properties();
// FileInputStream fis = null;
        try {
// Read the configuration file in the first way
// jdbc.properties By default, the file is under the current Module
// fis = new FileInputStream("jdbc1.properties");
// fis = new FileInputStream("src\\jdbc.properties");
// pros.load(fis);
// Read the configuration file in the second way
            ClassLoader cl = ClassLoaderTest.class.getClassLoader();
// The getResourceAsStream() method identifies the path under SRC of the current Module by default
            InputStream is = cl.getResourceAsStream("jdbc1.properties");
            pros.load(is);


            String user = pros.getProperty("user");
            String password = pros.getProperty("password");
            System.out.println("user:" + user + "Password." + password);
            // user: no more than password: abc123
            // user: no more than 1 password: abc123

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
// try {
// if (null == fis)
// fis.close();
// } catch (IOException e) {
// e.printStackTrace();
/ /}}}}Copy the code