2 annotation reflection and dynamic proxy

1.2 annotation reflection and dynamic proxy

1.2.1 reflection

Reflective entry Java lang.Class
Objects in daily development are divided into two types: basic type and reference type

Basic type, (8 fixed)                                         
  Integer: byte, short, int, long                                    
  Decimal: float, double                                    
  Character: char (2 Byte 65536 characters)                                   
  Boolean: boolean(1 Bit)                                    
reference type                                         
  All reference types inherit from java.lang.Object                              
  Classes, enumerations, arrays, and interfaces are all reference types                                    
  java.io.Serializable Interface, wrapper class of basic type (e.g java.lang.Double)It is also a reference type
  The reference type occupies 4 bytes

1. There are three ways to obtain class objects

(1) Object * *** getClass() method

When there is already 1 object, use the object getClass() returns the class of this object

String str = "abcd";
Class<?> clazz = str.getClass();  //The returned object clazz is of type String. 
(2) class * *** class syntax

If no object is created, use the class name followed by class

Class<?> clazz  = String.class;
Class<?> clazz1 = int.class;
String str = c.newInstance();  //Get this class and new out the object 
//This method can be used not only for reference types, but also for basic types.
(3)Class**.**forName()

In case of hidden class, class Class returned in the form of forname ("package name. Class name")

//General use
Class<?> cl = Class.forName("com.android.auto");
Class<?> c2 = Class.forName(String.class.getName()); //Complete package name + class name
//Inner class
Class<?> c3 = Class.forName("com.example.auto$Phone"); 

be careful:
Print object of class:

Class<?> cl = String.class;
System.out.println(cl);
System.out.println(cl.getName());      //Package name + class name
System.out.println(cl.getSimpleName());//Class name

//Print:
class java.lang.String
java.lang.String
String

Example of obtaining class object:

//The first way is to get the Class object
Student stu1 = new Student(); //This new generates a Student object and a Class object.
Class<?> stuClass = stu1.getClass();//Get Class object

//The second way is to get the Class object 
Class<?> stuClass2 = Student.class; 
System.out.println(stuClass == stuClass2);//The Class object obtained in the first method is the same as that obtained in the second method

//The third way is to get the Class object
try { 
    //The first way is to note that this string must be the real path, that is, the class path with package name and package name Class name
    Class<?> stuClass3 = Class.forName("com.Student");
    Class<?> stuClass3 = Class.forName(Student.class.getName()); //Mode 3 second
    System.out.println(stuClass3 == stuClass2);//Judge whether the three methods obtain the same Class object
} catch (ClassNotFoundException e) {
    e.printStackTrace(); 
}

2. Method of class object

common methodexplain
getName():StringReturns the Class of the entity (Class, interface, array Class, primitive type or invalid) represented by the Class object as a String.
getPackage()Get packages for this class
getSuperClass():ClassReturns the Class representing the direct superclass (Class, interface, primitive type or blank) of the entity represented by Class.
getInterfaces():Class[]Returns the interface directly implemented by the class or interface represented by the object.
isArray():booleanDetermines whether this Class object represents an array Class
isEnum():booleanAnd returns true only when the class is declared as an enumeration in the source code.
isInterface():booleanDetermines whether the specified Class object represents the interface type.
isPrimitive():booleanDetermines whether the specified Class object represents a base type
Common construction methodsexplain
Constructor [] getConstructors()Get all public constructor methods
Constructor [] getDeclaredConstructors(). get all construction methods without distinguishing access modifiers
getDeclaredConstructor(Class<?>... parameterTypes)Gets the parameter class of the specified constructor If class is a basic type, for example: int.class float class
Get common methods of Methodexplain
getMethods()Get all public methods
getDeclaredMethod(String name, Class<?>... parameterTypes))Get infinite qualifier method
Common methods of getting fileexplain
getFields()Get all public variables
getDeclaredField()Get indefinite symbolic variable

Examples of common methods

Class<?> clazz1 =Student.class;
String className = clazz.getName();     //Get full class name
System.out.println("className: "+className);
if(clazz.isArray()) {                  //Determine whether it is an array
    System.out.println("isArray");
}else if (clazz.isInterface()) {       //Determine whether it is an interface
    System.out.println("isInterface");
}else if (clazz.isPrimitive()){        //Determine whether it is a basic type
    System.out.println("Primitive");
}
if(clazz.isInstance(servant))          //Determine whether it is a type
{
    System.out.println("isInstance");
}

3. Class instantiation

XXX.class.newInstance() must obtain permission

//jdk8
String str = String.class.newInstance()
//jdk9 first obtains the constructor, and then passes the constructor new
Constructor constructor = String.class.getDeclaredConstructor()  
constructor.setAccessible(true);
String str = constructor.newInstance();//Nonparametric construction
constructor.setAccessible(false);

4.Constructor

1. Get all public construction methods

public Constructor [] getConstructors()

2. Obtain all construction methods without distinguishing access modifiers

public Constructor [] getDeclaredConstructors()

3. Get the specified construction method

public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
  // Class<?>...  Parameter classes in parametertypes If class is a basic type, for example: int.class float class

For example:

Class clazz = Class.forName("fanshe.Student");
//Get all public constructor methods
Constructor[] conArray = clazz.getConstructors();
for(Constructor c : conArray){
    System.out.println(c);
}
//All construction methods (including: private, protected, default, public)
Constructor[]conArray = clazz.getDeclaredConstructors();
for(Constructor c : conArray){
System.out.println(c);
}

5. Introduction to field member variables

Each member variable has a type and a value. java.lang.reflect.Field provides us with the method to obtain the type of the member variable of the current object and reset the value
(1) Get variable name

Field.getName(): Returns the name of this variable

(2) Gets the type of the variable

Field.getType(): Returns the type of this variable
Field.getGenericType(): If the current property has a signature property type, it will be returned; otherwise, it will be returned Field.getType()

(3) Gets the modifier of the member variable

Field.getModifiers() Method to get the modifier of the current member variable     
    Member variables can be decorated with the following modifiers:
    Access control character: public, protected, private
    Restrict to only one instance: static
    Not allowed to modify: final
    Will not be serialized: transient
    Consistency of thread shared data: volatile

(4) Gets and modifies the value of a member variable
Get variable:

public Field getField(String name) Public member field,name The name of the field.
public Field[] getFields()      All public field arrays
public Field getDeclaredField(String name) //In common use, you can get the publi, protect, default and privat e modified fields of the current class
public Field[] getDeclaredFields()    
Return a Field[]Array public, protected, default (package level private), and private fields, but excluding inherited fields.

Modify variables:

field.setAccessible(true)
field.setAccessible(false)
Field.set(Object obj, Object value)   //Set the value object to obj and the variable field defined by final Set cannot be changed
Object Field.get(Object obj)          //Get file variable from Object
    Common errors 
    1 : Unable to convert type java.lang.IllegalArgumentException f.set(ft, new Integer(43));
    2: Reflection non public Caused by variable NoSuchFieldException
    3 : modify final Caused by a variable of type IllegalAccessException

give an example:

For example:
//1. Get Class object
Class stuClass = Class.forName("fanshe.field.Student");
//2. Get field
System.out.println("************Get all public fields********************");
Field[] fieldArray = stuClass.getFields();
 for(Field f : fieldArray){
    System.out.println(f);
}
System.out.println("************Get all fields(Including private, protected, default)********************");
fieldArray = stuClass.getDeclaredFields();
for(Field f : fieldArray){
   System.out.println(f);
}
be careful: final Defined variables field.set Can't change

6.Method reflection

Inherited methods (including overloaded, overridden, and hidden) are enforced by the compiler and cannot be reflected. Therefore, when reflecting the method of a class, the method of the parent class is not considered, and only the method of the current class is considered. Each method is composed of modifiers, return values, parameters, annotations and thrown exceptions

(1) Get function of member method
Method  getMethod(String name, Class... parameterTypes)  Public member method, parameterType parameter   Method[] getMethods()  Public method, return Method An array of objects (including those declared by the class or interface and those inherited from the superclass and superinterface)

Method  getDeclaredMethod(String name, Class... parameterTypes)  Commonly used
 Return a Method Object whose name is specified as name,Includes public, protected, default (package) access, and private methods, but excludes inherited methods. Method[] getDeclaredMethods()                                        
return Method Object, including public, protected, default (package) access and private methods, but excluding inherited methods
(2) Call member method
//1. Set setAccessible property to true:
method.setAccessible()To change                                          
//2.invoke call
method.invoke(Object obj,arg...)

Example:
public class Test {
    private void fun() {}
    private static void fun1() {}
}
Class<?> clazz = Test.class;
Constructor<T> con = clazz.getDeclaredConstructor();
Test t = con.newInstance();
Method method = clazz.getDeclaredMethod("fun",null);
method.setAccessible(true);
method.invoke(t,null);  
Method method = clazz.getDeclaredMethod("fun1",null);
method.invoke(null,null) 
method.setAccessible(false);
be careful:When the called method is a static member, the method is method.invoke(null,xxx); The incoming object can be null
(3) Parameterless member method call
Example:
private void setButtonListener(){}                                            

//Reflection call
Methodmethod = mockBtAddPhone.getClass().getDeclaredMethod("setButtonListener",null);
method.setAccessible(true);      
Object result = method.invoke(mockBtAddPhone,null);
//Or object result = method invoke(mockBtAddPhone);      
method.setAccessible(false);    //Set to false 
(4) Member method call with one parameter
Example:
private void  set ButtonListener(int i) {}

//Reflection call
Method method = mockBtAddPhone.getClass().getDeclaredMethod("setButtonListener",int.class);                                        
method.setAccessible(true);
Object result = method.invoke(mockBtAddPhone,1);//The second parameter is the parameter of the formal code interface
method.setAccessible(false); // Set to false
(5) Member method call with multiple parameters
public void BTAdapterOnConnectionChangedUpdate(byte index, long devAdress, String devName, int func, byte result){}                   

//Reflection call
Class[] argTypes1=new Class[5];                                       
argTypes1[0]=byte.class;                                        
argTypes1[1]=long.class;                                        
argTypes1[2]=String.class;                                        
argTypes1[3]=int.class;                                        
argTypes1[4]=byte.class;                                                                           
Method method1 = MyBTAddPhoneListenerClazz.getDeclaredMethod("BTAdapterOnConnectionChangedUpdate", argTypes1);//argTypes1 passed is the parameter table of the code interface                  
method1.setAccessible(true);                                        
Objectresult1 = method1.invoke(obj,newObject[{(byte)0,1,null,1(byte)0});
method.setAccessible(false); // Set to false    
(6) About the call of inner class

The internal non static class holds this of the external class by default

The class containing BlueTooth in the Sceen test class calls the onChange method in the BlueTooth class

public class Screen {
    class BlueTooth {
            public void onChange(String _str,int _num){
                System.out.println("Calling internal class succeeded :"+_str+" "+_num);
         }
    }
}
Calling method:
    1.Get the external class first
    2.Get the inner class through the constructor, new When an object is exited, an external class is passed in this
    3.Method call
 be careful:
    Constructor parameter of internal class, with external class by default

//Get external class
Class<?> clazz5 = Screen.class;
Screen screen1 = (Screen) clazz5.newInstance();
//Get the internal class, and new out the object through the constructor
Class<?> clazz6 = Class.forName("com.Main.Screen$BlueTooth");
Constructor<?>[] constructors = clazz6.getDeclaredConstructors();
for (Constructor<?> con: constructors){
System.out.println(con);//com.Main.Screen$BlueTooth(com.Main.Screen)
}
constructors[0].setAccessible(true);
Object objects = constructors[0].newInstance(clazz5.newInstance());
constructors[0].setAccessible(false);
//method call
Class<?>[] args1 = new Class[2];
args1[0]=String.class;
args1[1]=int.class;
Method method = clazz6.getDeclaredMethod("onChange",args1);
method.setAccessible(true);
method.invoke(objects,"HH",123);
method.setAccessible(false);
(7) About calling member variables

Call the fun3() interface in the Screen class. In the fun3() interface, you need to judge the num in MMvvM

Calling method:
    1.class.class   Get class( Screen). 
    2.Field     Get member variable( MvvM)
    3.field1.set  modify MvvM in num Value of
    4.field.set   take MvvM Set variable to class( Screen)inside
    5.method.invo  Method call 
--------------
public class Screen {
    private MVVM mvm;
    public Screen(){
        System.out.println("Screen() ");
        mvm = MVVM.getInstance();
    }
    public void fun3(int _num){
    if (mvm.getNum()==_num){
        System.out.println("Call condition branch succeeded mvm.getNum()==_num");
    }else {
        System.out.println("Call condition branch succeeded mvm.getNum()!=_num");}
    }
}
------------
public class MVVM {
    private int num;
    private static MVVM mvvm;
    public static MVVM getInstance(){
    if (mvvm==null){
        mvvm = new MVVM();
        }
    return mvvm;
    }
    public void setNum(int _num){this.num=_num;}
    public int getNum(){return this.num;}
}
//Conditional branch call
try {
    //Get Screen class
    Class<?> clazz3 = Screen.class;
    Screen screen1 = (Screen) clazz3.newInstance();
    Class<?>[] args1 = new Class[1];
    args1[0]=int.class;
    Method method = clazz3.getDeclaredMethod("fun3",args1);
    Field field = clazz3.getDeclaredField("mvm");

    //Get MVVM class and set 100 to num variable
    Class<?> inner = MVVM.class;
    MVVM mvvm = (MVVM) inner.newInstance();
    Field field1 = inner.getDeclaredField("num");
    field1.setAccessible(true);
    field1.set(mvvm,100);
    field1.setAccessible(false);

    //Set mvvm to screen in screen1
    field.setAccessible(true);
    field.set(screen1,mvvm);
    field.setAccessible(false);

    method.setAccessible(true);
    method.invoke(screen1,100);
    method.setAccessible(false);

} catch (NoSuchMethodException |NoSuchFieldException |IllegalAccessException |InstantiationException |InvocationTargetException e) {
    e.printStackTrace();
}
(8).invoke return value judgment
If it is string Type return function                                        
	Class<>  clazz=  InvokeObj.class;                                 
	Method method4 = clazz.getMethod("StringShow", String.class);         
	String result = (String) method4.invoke(clazz.newInstance(), "Thinking in java");                   Assert.assertEquals("Thinking in java",result);

If it is void Function, return null
    Assert.assertEquals(null,result);                                     
	public Object invoke(Objectobj,Object...args)                                               

Called on the specified object with the specified parameters Method Object represents the underlying method. Individual parameters are automatically unpacked to match the basic formal parameters. The basic parameters and reference parameters are subject to method call conversion as needed.            
If the underlying method is static, the specified can be ignored obj Parameters. This parameter can be null. 
If the shape parameter required by the underlying method is 0, the provided args The array length can be 0 or null.          If the underlying method is static and the class that declares the method has not been initialized, it will be initialized. 
If the method completes normally, return the value returned by the method to the caller; If the value is a basic type, wrap it appropriately in the object first. However, if the type of the value is a set of basic types, the array elements are not wrapped in the object; In other words, an array of primitive types is returned. If the return type of the underlying method is void,The call returns null

1.2.2 dynamic agent

Git
Proxy concept: provide a proxy object to the target object, and the proxy object controls the reference to the target object.
Purpose:
(1) Through the introduction of proxy object to indirectly access the target object, so as to prevent unnecessary complexity to the system.
(2) Enhance the original business logic through proxy objects.

(1) Static proxy: one-to-one relationship
Static proxy:example
 Interface: Start
Start ->realization  RealStart
Start ->realization  ProxyStart 
ProxyStart Is a proxy class containing RealStart

public interface Start {
    public void bookTicket();
    public void Config();
    public void CollectMoney();
    public void sing();
}
public class RealStart implements Start{
    @Override
    public void bookTicket() {
        System.out.println("RealStart bookTicket");
    }
@Override
public void Config() {
    System.out.println("RealStart Config");
    }
@Override
public void CollectMoney() {
    System.out.println("RealStart CollectMoney");
    }
@Override
public void sing() {
    System.out.println("RealStart sing");
    }
}
public class ProxyStart implements Start {
    private Start start;
    public ProxyStart(Start _start) {
        start=_start;
}
@Override
public void bookTicket() {
    System.out.println("ProxyStart bookTicket");
}
@Override
public void Config() {
    System.out.println("ProxyStart Config");
}
@Override
public void CollectMoney() {
    System.out.println("ProxyStart CollectMoney");
}
@Override
public void sing() {
        start.sing();
    }
}
public static void main(String[] args) {
    System.out.println("-------------Simple agent--------------");
    Start realStart = new RealStart();
    Start proxyStart = new ProxyStart(realStart);

    proxyStart.CollectMoney();
    proxyStart.bookTicket();
    proxyStart.sing();
}
(2) Dynamic proxy: one to many

The proxy method created by the proxy class when the program is running is called dynamic proxy. Compared with static proxy, the advantage of dynamic proxy is that it can easily handle the functions of the proxy class in a unified way without modifying the methods in each proxy class

In java Lang.reflect package provides a Proxy class and an InvocationHandler interface, through which JDK dynamic Proxy classes and dynamic Proxy objects can be generated.

Dynamic proxy steps:
1. Real object interface
2. Create real object implementation interface
3. Create an object to implement InvocationHandler interface
4. Through proxy newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Shop.class},invocationHandler); Implementation agent

Keywords: Java reflection Dynamic Proxy

Added by ionik on Sun, 13 Feb 2022 14:42:04 +0200