[Java] Sping basic knowledge-Reflection

Source: Internet
Author: User

[Java] Sping basic knowledge-Reflection
The Java language allows indirect Class operations in a programmatic manner. After the Class file is loaded by the Class loader, a metadata object describing the Class structure will be formed in the JVM, the metadata object can be used to obtain the structure information of the Class, such as constructor, attribute, and method. Java allows users to indirectly call the Class object function through the meta information object related to this Class, which opens up a way to operate Class objects in a programmatic way.

Simple instance

We will start from a simple example to explore the Java reflection mechanism. The following Car class has two constructors, two methods, and three attributes, as shown in code list 3-9:

Code List 3-9 Car
Java code

  1. Package com. baobaotao. reflect;
  2. Public class Car {
  3. Private String brand;
  4. Private String color;
  5. Private int maxSpeed;
  6.  
  7. // ① Default constructor
  8. Public Car (){}
  9.  
  10. // ② Constructor with Parameters
  11. Public Car (String brand, String color, int maxSpeed ){
  12. This. brand = brand;
  13. This. color = color;
  14. This. maxSpeed = maxSpeed;
  15. }
  16.  
  17. // ③ Method without Parameters
  18. Public void introduce (){
  19. System. out. println (brand: + brand +; color: + color +; maxSpeed: + maxSpeed );
  20. }
  21. // Omit the getter/Setter method of the Parameter
  22. ...
  23. }
    Generally, we use the following code to create a Car instance:
    Java code
    1. Car car = new Car ();
    2. Car. setBrand (Red Flag CA72 );
      Or:
      Java code
      1. Car car = new Car (Red Flag CA72, black );

        The above two methods both use the traditional method to directly call the method of the target class. Below we use the Java reflection mechanism to indirectly operate the target class in a more general way:

        Code List 3-10 ReflectTest
        Java code
        1. Package com. baobaotao. reflect;
        2. Import java. lang. reflect. Constructor;
        3. Import java. lang. reflect. Field;
        4. Import java. lang. reflect. Method;
        5. Public class ReflectTest {
        6. Public static Car initByDefaultConst () throws Throwable
        7. {
        8. // ① Get the Car class object through the Class Loader
        9. ClassLoader loader = Thread. currentThread (). getContextClassLoader ();
        10. Class clazz = loader. loadClass (com. baobaotao. reflect. Car );
        11.  
        12. // ② Obtain the default constructor object of the class and instantiate the Car through it
        13. Constructor cons = clazz. getDeclaredConstructor (Class []) null );
        14. Car car = (Car) cons. newInstance ();
        15.  
        16.  
        17. // ③ Set attributes through reflection
        18. Method setBrand = clazz. getMethod (setBrand, String. class );
        19. SetBrand. invoke (car, Red Flag CA72 );
        20. Method setColor = clazz. getMethod (setColor, String. class );
        21. SetColor. invoke (car, black );
        22. Method setMaxSpeed = clazz. getMethod (setMaxSpeed, int. class );
        23. SetMaxSpeed. invoke (car, 200 );
        24. Return car;
        25. }
        26.  
        27. Public static void main (String [] args) throws Throwable {
        28. Car car = initByDefaultConst ();
        29. Car. introduce ();
        30. }
        31. }
          Run the above program and print the following information on the console:
          Reference brand: Red Flag CA72; color: black; maxSpeed: 200

          This shows that all the functions of the Class can be called programmatically, which is consistent with the effect of directly calling the Class functions through constructor and method, except that the former is called indirectly, the latter is called directly.

          In ReflectTest, several important reflection classes are used: ClassLoader, Class, Constructor, and Method. Through these reflection classes, the functions of the target Class can be indirectly called. At ①, we get the ClassLoader of the current thread and load the reflection instance corresponding to the Car class through the specified fully qualified class "com. baobaotao. beans. Car. In section ②, we obtain the cons of the Car cons through the reflection object of the Car, and instantiate the Car object through the newInstrance () method of the constrance object, the effect is equivalent to new Car (). At ③, we use the getMethod (String methodName, Class paramClass) of the reflection Class Object of Car to obtain the Setter method object of the attribute. The first parameter is the method name of the target Class; the second parameter is the object type of the method input parameter. After obtaining the method reflection Object, you can call the method of the target class through the invoke (Object obj, Object param) method. The first parameter of this method is the target class Object instance of the operation; the second parameter is the input parameter of the target method.

          In code listing 3 10, the information shown in bold is the metadata of the target class through reflection. If we provide this information in a configuration file, you can use the reflection function of Java to compile a common code to instantiate a Car-like class and call functions.

          ClassLoader

          Working Mechanism of the Class Loader

          The class loader is used to find the class code file and construct a component that represents the object within the JVM. In Java, to load a class into JVM, follow these steps:

          • [1.] load: Find and import Class files;
            [2.] link: perform verification, preparation, and resolution steps. The resolution steps are optional:
            [2.1] Check: Check whether the data in the loaded Class file is correct;
            [2.2] Preparation: allocate storage space to static variables of the class;
            [2.3] parsing: converting a symbolic reference into a direct reference;
            [3.] 3. Initialization: Class static variables and static code blocks are initialized.

            ClassLoader and its sub-classes are responsible for Class loading. ClassLoader is an important system component for Java runtime. It is responsible for searching and loading Class bytecode files during runtime. At runtime, the JVM generates three ClassLoader: Root loader, ExtClassLoader (Extended Class Loader), and AppClassLoader (system class loader ). The root loader is not a subclass of ClassLoader. It is written in C ++, so we cannot see it in Java. The root loader is responsible for loading the core class library of JRE, for example, rt under the JRE target. jar and charsets. jar. Both ExtClassLoader and AppClassLoader are subclasses of ClassLoader. ExtClassLoader is responsible for loading the JAR class package in ext In the JRE extension directory, and AppClassLoader is responsible for loading the class package in the Classpath path.

            There is a parent-child relationship between these three class loaders, that is, the root loader is the parent loader of ExtClassLoader, and ExtClassLoader is the parent loader of AppClassLoader. By default, we can use AppClassLoader to load the application class. We can do an experiment:

            Code List 3-11 ClassLoaderTest
            Java code
            1. Public class ClassLoaderTest {
            2. Public static void main (String [] args ){
            3. ClassLoader loader = Thread. currentThread (). getContextClassLoader ();
            4. System. out. println (current loader: + loader );
            5. System. out. println (parent loader: + loader. getParent ());
            6. System. out. println (grandparent loader: + loader. getParent (). getParent ());
            7. }
            8. }
              Run the above Code and output the following information on the console:
              Reference current loader: sun. misc. Launcher $ AppClassLoader @ paif71a
              Parent loader: sun. misc. Launcher $ ExtClassLoader @ 15601ea
              // ① The root loader cannot be accessed in Java, so null is returned.
              Grandparent loader: null

              Through the above output information, we know that the current ClassLoader is AppClassLoader, the parent ClassLoader is ExtClassLoader, and the grandfather ClassLoader is the root class loader, because it cannot be obtained in Java, therefore, only null is returned.

              The JVM uses the "full responsibility delegation mechanism" to load classes. "full responsibility" means that when a ClassLoader loads a class, unless it explicitly uses another ClassLoader, classes dependent on and referenced by this class are also loaded by this ClassLoader. The "delegation mechanism" refers to entrusting the parent loader to find the target class first, you can find and load the target class from your own class path only when you cannot find it. This is from a security perspective. Imagine how terrible the consequences would be if someone compiled a malicious basic class (such as java. lang. String) and loaded it into the JVM. However, with the "full responsibility for delegation mechanism", java. lang. String is always loaded by the root loader, which avoids the above events.

              ClassLoader important methods

              In Java, ClassLoader is an abstract class located in the java. lang package. The following describes some important interface methods of this class:
              • The Class loadClass (String name) name parameter specifies the name of the Class to be loaded by the Class loader. You must use a fully qualified Class name, such as com. baobaotao. beans. Car. This method has an overloaded method loadClass (String name, boolean resolve). The resolve parameter tells the Class Loader whether to parse the class. Before initializing a class, you should consider parsing the class, but not all classes need to be parsed. If the JVM only needs to know whether the class exists or find out the super class of the class, therefore, resolution is not required.
              • Class defineClass (String name, byte [] B, int off, int len) converts the byte array of the Class file into a java. lang. Class Object in the JVM. Byte Arrays can be obtained from local file systems and remote networks. Name is the fully qualified class name corresponding to the byte array.
              • Class findSystemClass (String name) loads the Class file from the local file system. If this Class file does not exist in the local file system, a ClassNotFoundException exception is thrown. This method is the default loader system used by JVM.
              • Class findLoadedClass (String name) calls this method to check whether the ClassLoader has loaded a Class. If it has been loaded, the java. lang. Class Object is returned; otherwise, null is returned. If an existing class is forcibly loaded, a link error is thrown.
              • ClassLoader getParent () obtains the parent loader of the Class Loader. Apart from the root loader, all class loaders have only one parent loader, the parent loader of ExtClassLoader is the root loader. Because the root loader is not written in Java, it cannot be obtained and null is returned.

                In addition to the default three class loaders of JVM, you can write your own third-party class loaders to meet some special requirements. After the class file is loaded and parsed, a corresponding java will be available in the JVM. lang. class description object. all instances of this Class have reference to this Class description object, and the Class description object has reference to the associated ClassLoader, as shown in 4-4.



                Each Class has a corresponding java. lang. Class Object in JVM. It provides a description of the Class structure information. Arrays, enumerations, annotations, and basic Java types (such as int and double), and even void all have corresponding Class objects. Class does not have a public constructor. Class objects are automatically constructed by JVM by calling the defineClass () method in the Class Loader during Class loading.

                Java reflection mechanism

                Class reflection object describes the Class semantic structure. You can obtain reflection objects of Class elements such as constructors, member variables, and methods from Class objects, and operate the object class through these reflection objects programmatically. These reflection object classes are defined in the java. reflect package. The following are the three most important reflection classes:
                • ? Constructor: Constructor reflection Class. You can use the Class # getConstructors () method to obtain an array of all Constructor reflection objects of the Class. In JDK5.0, you can also use getConstructor (Class... parameterTypes) to obtain the constructor reflection object with specific input parameters. One of the main methods of Constructor is newInstance (Object [] initargs). This method can be used to create an instance of an Object class, which is equivalent to the new keyword. In JDK5.0, this method evolved into a more flexible form: newInstance (Object... initargs ).
                • ? Method: The reflection Class of the Class Method. You can use the Class # getDeclaredMethods () Method to obtain all methods of the Class. The reflection Class Object array Method []. In JDK5.0, you can use getDeclaredMethod (String name, Class... parameterTypes) to obtain the method of a specific signature. name is the method name, and Class... is the list of input parameter types of the method. The main Method is invoke (Object obj, Object [] args). obj indicates the target Object of the operation. args indicates the Method input parameter, code listing 3 10 ③ demonstrates how to use this reflection class. In JDK 5.0, the method format is adjusted to invoke (Object obj, Object... args ). In addition, there are many methods for getting more information about the Class Method: 1) Class getReturnType (): Get the type of the return value of the Method;
                  2) Class [] getParameterTypes (): Get the input parameter type array of the method;
                  3) Class [] getExceptionTypes (): obtains an array of exception types of methods;
                  4) Annotation [] [] getParameterAnnotations (): Get the Annotation information of the method, the new method in JDK 5.0;
                • ? Field: Reflection Class of member variables of the Class. The Class # getDeclaredFields () method can be used to obtain the array of member variables reflection objects of the Class, and the Class # getDeclaredField (String name) can be used) obtains the member variable reflection object of a specific name. The main method of the Field class is set (Object obj, Object value). obj indicates the target Object for the operation, and value indicates the value of the member variable of the target Object. If the member variable is of the base type, you can use the value setting method with the type name provided in the Field class, such as setBoolean (Object obj, boolean value), setInt (Object obj, int value.
                  In addition, Java also provides the Package reflection class for the Package, and the AnnotatedElement reflection class for the annotation in JDK 5.0. In short, the Java reflection system ensures that all elements in the target class can be accessed in a programmatic manner. For private or protected member variables and methods, as long as the JVM security mechanism permits, you can also call it through reflection. See the following example:

                  Code List 3-12 PrivateCarReflect
                  Java code
                  1. Package com. baobaotao. reflect;
                  2. Public class PrivateCar {
                  3. // ① Private member variable: the traditional class instance call method can only be accessed in this class
                  4. Private String color;
                  5. // ② Protected method: the traditional class instance call method can only be accessed in the subclass and the package
                  6. Protected void drive (){
                  7.  
                  8. System. out. println (drive private car! The color is: + color );
                  9. }
                  10. }
                    Both the color variable and the drive () method are private. Private variables and private methods cannot be accessed externally through class instance variables, but the reflection mechanism can bypass this restriction:

                    Code List 3-13 PrivateCarReflect
                    Java code
                    1. ...
                    2. Public class PrivateCarReflect {
                    3. Public static void main (String [] args) throws Throwable {
                    4. ClassLoader loader = Thread. currentThread (). getContextClassLoader ();
                    5. Class clazz = loader. loadClass (com. baobaotao. reflect. PrivateCar );
                    6. PrivateCar pcar = (PrivateCar) clazz. newInstance ();
                    7.  
                    8. Field color== clazz. getDeclaredField (color );
                    9. // ① Cancel Java access check to access private variables
                    10. Colorparser. setAccessible (true );
                    11. Colorclassification. set (pcar, red );
                    12.  
                    13. Method driveMtd = clazz. getDeclaredMethod (drive, (Class []) null );
                    14. // Method driveMtd = clazz. getDeclaredMethod (drive); used in JDK5.0
                    15.  
                    16. // ② Cancel Java access check to access the protected Method
                    17. DriveMtd. setAccessible (true );
                    18. DriveMtd. invoke (pcar, (Object []) null );
                    19. }
                    20. }
                      Run this class to print the following information:
                      Reference drive private car! The color is: red

                      When accessing private and protected member variables and methods, you must use the setAccessible (boolean access) method to cancel the Java language check. Otherwise, the IllegalAccessException will be thrown. If the JVM security manager sets the corresponding security mechanism, a SecurityException is thrown when this method is called.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.