Java reflection mechanism and Application

Java reflection mechanism and Application

1. Java reflection

In the running state, for any class, you can get all the properties and methods of the class, and for any object, you can call any of its methods and properties (including private methods and properties). This dynamically obtained information and the function of dynamically calling the methods of the object are called the reflection mechanism of java language.

2. Java program running process

java source file (. java file) – > compiled by Javac compiler – > binary bytecode file (. Class file) – > JVM class loader loading – > interpreter interpretation – > machine code (machine understandable code) – > operating system platform

3. Java reflection function and principle

3.1 reflection

Through reflection, you can dynamically create objects and call their properties at run time without knowing who the running object is at compile time in advance.

3.2 reflection principle

In short, it is to obtain the properties, methods and other information of class objects through decompilation.
The reflection mechanism of Java is that it is not sure which class is loaded at compile time, but it is loaded, detected and self reviewed when the program is running. Use classes that are not known at compile time.

Decompile: class–>. java

Note: when Jvm loads bytecode files from local disk into Jvm memory, Jvm will automatically create a class object. That is, a class will only produce one class object.
Reason: class loading mechanism - parent delegation mechanism

4. Class loading mechanism - parental delegation mechanism

The JVM provides a three-tier ClassLoader:

  • Bootstrap classloader: it is mainly responsible for loading the core class library (java.lang. * etc.) and constructing ExtClassLoader and APPClassLoader.

  • ExtClassLoader: mainly responsible for loading some extended jar s in jre/lib/ext directory.

  • AppClassLoader: mainly responsible for loading the main function class of the application.

The class loading process under the parental delegation mechanism is shown in the figure below:

When considering the existence of a user-defined class loader, the first step in loading a class is to check whether the class has been loaded from the user-defined class loader. If it has not been loaded, delegate upward and get the parent class constructor AppClassLoader loader for inspection. If it has not been loaded, delegate upward in turn, Constantly check whether the parent class loader has loaded the class. If it has been loaded, you do not need to load it again and return directly. If the class is not loaded after being checked by the bootstrap classloader, load the class from the parent class downward. If the bootstrap classloader cannot load this class, it will be loaded by the subclass loader and loaded downward in turn.

Role of parental delegation mechanism:

  • Avoid secondary loading of the same class
  • Prevent the core class library API from being modified

5. Java reflection usage

5.1 three ways to obtain class objects

  • Get the Class object through the static method forName in the Class
Class clazz1 = Class.forName("Fully qualified class name");
  • Pass the class name class
Class clazz2  = Demo.class;
  • Get the bytecode file object of the class through the instance of the class
Class clazz3 = p.getClass();

5.2 reflection acquisition class attributes, methods and construction methods

public class TargetDemo {

    public TargetDemo (){}

    public TargetDemo (String str){
        this.str = str;
        System.out.println("Execution constructor method");
    }

    public String str = "hello";

    private String username;

    private int age;

    public void print(){
        System.out.println("TargetDemo");
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getAge() {
        return age;
    }

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

    public static void main(String[] args) {
        try {
            //Get class object
            Class<?> target = Class.forName("com.torlesse.consumer.test.TargetDemo");
            //Getting the public part of the class object property cannot access the private part
            for (Field field : target.getFields()) {
                System.out.println(field.getName());
            }

            //Get constructor
            Constructor<?> targetDeclaredConstructor = target.getDeclaredConstructor(String.class);
            Object o = targetDeclaredConstructor.newInstance("demo");
            System.out.println(o);

            //Instantiate object
            Object o1 = target.newInstance();
            //Acquisition method
            Method method = target.getMethod("print");
            method.invoke(o1,null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

result:

6. Run the specified package to get the specified annotation class

Scheme usage: reflections framework
Dependent import:

<dependency>
            <groupId>org.reflections</groupId>
            <artifactId>reflections</artifactId>
            <version>0.9.11</version>
        </dependency>

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>21.0</version>
        </dependency>
//Tag class annotation
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface JobClassInterface {

}
//Annotation of marking method
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)

@Documented
public @interface JobMethodInterface {
    String jobName();

}
//Enter the package name to scan
Reflections f = new Reflections("com.torlesse.xxx.xxx");

//Input target annotation class
Set<Class<?>> set = f.getTypesAnnotatedWith(JobClassInterface.class);

Iterator<Class<?>> iterator = set.iterator();
while (iterator.hasNext()){
   Class<?> next = iterator.next();
   for (Method method : next.getMethods()) {
   for (Annotation declaredAnnotation : method.getDeclaredAnnotations()) {
       if(declaredAnnotation instanceof JobMethodInterface){
           String targetName = ((JobMethodInterface)declaredAnnotation).jobName();
           if(targetName.equals(jobName)){
                method.invoke(next.newInstance(), null);
                return;
                }
             }
       }
   }
}

Java reflection mechanism and Application

Keywords: Java Back-end

Added by linusx007 on Fri, 11 Feb 2022 17:04:04 +0200