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 method | explain |
---|---|
getName():String | Returns 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():Class | Returns 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():boolean | Determines whether this Class object represents an array Class |
isEnum():boolean | And returns true only when the class is declared as an enumeration in the source code. |
isInterface():boolean | Determines whether the specified Class object represents the interface type. |
isPrimitive():boolean | Determines whether the specified Class object represents a base type |
Common construction methods | explain |
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 Method | explain |
getMethods() | Get all public methods |
getDeclaredMethod(String name, Class<?>... parameterTypes)) | Get infinite qualifier method |
Common methods of getting file | explain |
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