Reflection and custom annotation

Keywords: Java

reflex

What is reflection

Oracle's official interpretation of reflection:

Through reflection, we can get the member and member information of each type in the program or assembly at run time. The type of general objects in the program is determined at compile time, and Java reflection mechanism can dynamically create objects and call their properties. The type of such objects is unknown at compile time. Therefore, we can create objects directly through reflection mechanism, even if the type of this object is unknown at compile time.

The core of reflection

The core of Java reflection mechanism is to dynamically load classes and obtain class details when the program is running, so as to operate the properties and methods of classes or objects. The essence is that after the JVM obtains the class object, it decompiles it through the class object to obtain various information of the object

java is compiled and then executed. Load the required classes from. java file - >. Class file - > through the class loading mechanism, and the unused classes will not be loaded into the JVM. Through reflection, you can dynamically create objects and call their properties at run time, without knowing who the running objects are at compile time in advance.

Using the reflection mechanism, you can dynamically obtain the information of the current class, such as method information, annotation information, method parameters, attributes, etc

Advantages and disadvantages of reflection mechanism

A private property / method is defined in a class, but all properties can be accessed by using reflection, which will crack the private property

1. Advantages: obtain various contents of classes at run time and decompile them. For Java, a language that compiles first and then runs, it is convenient for us to create flexible code. These codes can be matched at run time without linking source code between components, making it easier to realize object-oriented.

2. Disadvantages:

(1) Reflection consumes some system resources, so if you don't need to create an object dynamically, you don't need to use reflection

(2) Reflection can ignore permission checking when calling methods, which may break encapsulation and lead to security problems

Application scenario of reflection

Decompile:. Class -- >. Java

1. Access the properties, methods and construction methods of java objects through reflection mechanism

2. JDBC load driver connection class.forname

Class.forName("com.mysql.jdbc.Driver"); // Dynamic loading mysql driver

3. Spring container framework IOC instantiation object

 <bean id="usr" class="com.ylc.UserEntity" />

4. Custom annotation takes effect (reflection + Aop)

5. Third party core framework mybatis orm

Use of reflection technology

Class represents the entity of a class and represents classes and interfaces in running Java applications

The Field class represents the member variables of the class (member variables are also called class properties)

The Method class represents the Method of the class

Constructor class represents the construction method of class

1.getField, getMethod and getCostructor methods can obtain the domain, method and constructor with the specified name.

2. The getfields, getMethods and getconstructors methods can obtain the public fields, methods and constructor arrays provided by the class, including the common members of the superclass.

3. The getdeclatedfields, getDeclatedMethods and getDeclaredConstructors methods can obtain all the fields, methods and constructors declared in the class, including private and protected members, but excluding members of the superclass.

The reflection mechanism creates objects in three ways

  • Get the class through the new object

          UserEntity userEntity = new UserEntity();
            Class userClass = userEntity.getClass();
            // The default execution is a parameterless constructor
            UserEntity user2 = (UserEntity) userClass.newInstance();
            System.out.println(user2==userEntity);//false
    
  • Get class directly

     Class userClass = UserEntity.class;
     UserEntity user2 = (UserEntity) userClass.newInstance();
     System.out.println(user2);
    
  • Get class by full class name (common)

     Class<?> aClass = Class.forName("com.ylc.entity.UserEntity");
            UserEntity user3 = (UserEntity) aClass.newInstance();
            System.out.println(user3);
    

During operation, only one Class object is generated for a Class

Reflection execution constructor

non-parameter constructor

 Class<?> userClass = Class.forName("com.ylc.entity.UserEntity");
 UserEntity userEntity1 = (UserEntity) userClass.newInstance();
 System.out.println(userEntity1);

Parameterized constructor

  Class<?> userClass = Class.forName("com.ylc.entity.UserEntity");
   Constructor<?> declaredConstructor1 = userClass.getDeclaredConstructor(String.class, Integer.class);
        UserEntity ylc = (UserEntity)declaredConstructor1.newInstance("ylc", 22);
        System.out.println(ylc.toString());

Reflection traverses attributes and assigns values

Reflection performs assignment to public attributes

The getFields method can only access public properties of a class

Class<?> userClass = Class.forName("com.ylc.entity.UserEntity");
Field[] fields = userClass.getFields();
for (Field field : fields) {
    System.out.println(field);
}

Reflection performs assignment to private attributes

Getdeclaraedfields can access all properties of the class

    Class<?> userClass = Class.forName("com.ylc.entity.UserEntity");
        Field[] fields = userClass.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field);
        }

Attribute assignment by reflection

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        Class<?> userClass = Class.forName("com.ylc.entity.UserEntity");
        UserEntity userEntity = (UserEntity)userClass.newInstance();
        //Properties found
        Field pubUserName = userClass.getDeclaredField("pubUserName");
        //Specifies which userEntity object to assign a value to
        pubUserName.set(userEntity,"ylc");
        System.out.println(userEntity.pubUserName);
    }

This is to assign a value to the public attribute. By default, you can only access the public attribute. If you want to access the private attribute, an error will be reported

Reflection does not have permission to access private properties. If you need access, you need to set the permission setAccessible

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        Class<?> userClass = Class.forName("com.ylc.entity.UserEntity");
        UserEntity userEntity = (UserEntity)userClass.newInstance();
        Field pubUserName = userClass.getDeclaredField("userName");
        //Set permissions
        pubUserName.setAccessible(true);
        pubUserName.set(userEntity,"ylc");
        System.out.println(userEntity.getUserName());
    }

Reflection call method

Reflection calls public methods

Class<?> aClass = Class.forName("com.ylc.entity.UserEntity");
UserEntity userEntity = (UserEntity) aClass.newInstance();
Method mayikt = aClass.getDeclaredMethod("mayikt");
//Execution method
mayikt.invoke(userEntity);

Reflection calls private methods. You need to turn on the access permission, otherwise you can't access it

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Class<?> userClass = Class.forName("com.ylc.entity.UserEntity");
        UserEntity o = (UserEntity)userClass.newInstance();
        Method method = userClass.getMethod("HelloWorld");
        Object invoke = method.invoke(o);
    }

userName.setAccessible(true);

Reflection calls method pass parameters

    private Integer sum(Integer a, Integer b) {
        return a + b;
    }
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
    Class<?> userClass = Class.forName("com.ylc.entity.UserEntity");
    UserEntity o = (UserEntity)userClass.newInstance();
    //Call method to pass parameters
    Method method = userClass.getDeclaredMethod("sum",Integer.class,Integer.class);
    method.setAccessible(true);
    Integer result = (Integer)method.invoke(o,1,2);
    System.out.println(result);
}

Cross generic checking by reflection

Generic validation is performed at compile time. Adding an int type will result in an error

After the compiler compiles, the class file can be cracked by reflection in the program

        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add("ylc");
        Class<? extends ArrayList> aClass = arrayList.getClass();
        Method addMethod = aClass.getDeclaredMethod("add", Object.class);
        addMethod.invoke(arrayList, 1);
        System.out.println(arrayList);

annotation

Annotation concept

Annotations are used to add additional information to class declarations. They can be marked on classes, fields, methods, etc. the compiler, JVM and developers can get the annotation information through reflection, and then do some related processing

Common notes

@Override can only be marked on the method that the child class overrides the parent class. It has the function of prompting

@The Deprecated annotation is used to indicate obsolete methods or classes

@SuppressWarnings("unchecked") are marked on the classes and methods that the compiler considers to be problematic to cancel the warning prompt of the compiler. The warning types include serial, unchecked, unused and all

Meta annotation

Meta annotations are used to specify some features of new annotations when declaring new annotations

@Target specifies the location of the new annotation, such as class, field, method, etc. the values include ElementType.Method, etc

@Target({ElementType.METHOD,ElementType.TYPE,ElementType.FIELD})

@Retention specifies when the information of the new annotation will be retained. The values include RetentionPolicy.RUNTIME, etc

@Inherited specifies that the new annotation can be inherited by the child class when it is marked on the parent class

Annotated Target

TYPE: Declaration of classes, interfaces (including annotation types) and enumerations

FIELD: FIELD declaration (including enumeration constants)

METHOD: METHOD declaration

PARAMETER: PARAMETER declaration

CONSTRUCTOR: CONSTRUCTOR declaration

LOCAL_VARIABLE: local variable declaration

ANNOTATION_TYPE: annotation type declaration

PACKAGE: PACKAGE declaration

TYPE_PARAMETER: type parameter declaration, introduced by Java se 8, can be applied to the generic declaration of classes

TYPE_USE: introduced by JavaSE8, this type includes type declaration and type parameter declaration

Get annotation information

Annotation method

    @DiyName
    private void HelloWorld() {
        System.out.println(" ...ylc.....");
    }

Custom annotation

@Target({ElementType.METHOD,ElementType.TYPE,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface DiyName {
}

Gets the annotation on the current method

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException {
        Class<?> userClass = Class.forName("com.ylc.entity.UserEntity");
        Object o = userClass.newInstance();
        Method diyMethod = userClass.getDeclaredMethod("HelloWorld");
        DiyName diyName = diyMethod.getDeclaredAnnotation(DiyName.class);
        System.out.println(diyName);
    }

Posted by bben95 on Fri, 26 Nov 2021 16:30:36 -0800