1.
{
class Perosn(){}
How to create objects of runtime classes through reflection
1.new + constructor (Person();)
By reflection
2.clazz.newInstance();
3. Class name. Class. Getdeclaraedconstructors(). Newinstance();
Get an instance of Class
1.Person.class;
2.Person p = new Perosn();
p.getClass();
Build some structures of Class
3. Call the static method in Class
Class.forName("relative directory of runtime class \ (root directory)")
}
1: Understanding of Reflection: Reflection is regarded as the key of dynamic language. The Reflection mechanism allows the internal information of any class to be obtained with the help of the Reflection API during program execution,
It can directly operate the internal properties and methods of any object
2: Frame = reflection + annotation + design pattern
3: Dynamics of reflection: examples in FanShe\src\Text\NewInstanceTest.
4: Functions provided by reflection mechanism
2
About java. Understanding of long.Class 1. Class loading process: After the program passes the java.exe command, one or more bytecode files (. Class) will be generated. Then we use the java.exe command to interpret and run a bytecode file. Equivalent to a bytecode file Load into memory. This process is called class loading. The class loaded into memory is called the runtime class The runtime Class is used as an instance of Class. 2. In other words, an instance of Class corresponds to a runtime Class. 3. The runtime classes loaded into memory will be cached in the cache for a certain time, and we can get them in different ways Class for this runtime.
3. Class loader
1. Function of class loader
Load the bytecode of the class file into memory, convert these static data into the runtime data structure of the method area, and then produce a java.lang.Class object of this class in the heap as the access entry for the class data in the method area
2. Use classloader to load files under SRC
Properties ps = new Properties(); //How to read the configuration file? At this time, the file is under the current module by default. // FileInputStream fis = new FileInputStream("L3.properties"); // ps.load(fis); //Method 2 for reading configuration files; Using ClassLoader //The configuration file defaults to src of the current module ClassLoader classLoader = ClassLoaderTest.class.getClassLoader(); InputStream is = classLoader.getResourceAsStream("L2.properties"); ps.load(is); String name = ps.getProperty("name"); String password = ps.getProperty("password"); System.out.println("name = "+name+" password = "+password); 4.
1. Create the object of the runtime class
//newInstance(); Call this method to create the object of the corresponding runtime class and internally call the empty parameter constructor of the runtime class. / / to create the object of the runtime class normally, requirements: / / 1. The runtime class must have an empty parameter constructor. / / 2. Access permissions must be sufficient. Usually public
//An empty parameter constructor is required in a javabean. 1. It is convenient to create the object of the runtime class through reflection. / / 2. When the subclass inherits the parent class, it is convenient to ensure that the parent class has this constructor when calling super() by default
Class<Person> clazz = Person.class; // Person o = clazz.newInstance(); //This method has been used by getdeclaraedconstructor(). Newinstance(); replace Person person = Person.class.getDeclaredConstructor().newInstance(); System.out.println(person);
2. Get some structures in the runtime class
--------------
Get constructor structure: public void test() { Class clazz = Person.class; //getConstructors() gets the constructors of all public of the current runtime class Constructor[] constructor = clazz.getConstructors(); for (Constructor c: constructor) { System.out.println(c); } //Getdeclaraedconstructors() gets all constructors of the current runtime class Constructor[] constructors = clazz.getDeclaredConstructors(); for (Constructor c: constructors) { System.out.println(c); } } //Gets the parent class of the runtime class @Test public void test2() { Class clazz = Person.class; Class superclass = clazz.getSuperclass(); System.out.println(superclass); //Get parent class with generics Type type = clazz.getGenericSuperclass(); System.out.println(type); } /* Gets the generic type of the parent class with the generic type */ @Test public void test3() { Class clazz = Person.class; Type genericSuperclass = clazz.getGenericSuperclass(); ParameterizedType parmeType = (ParameterizedType) genericSuperclass; //Get generic type Type[] actualTypeArguments = parmeType.getActualTypeArguments(); System.out.println(((Class)actualTypeArguments[0]).getName()); }
----------
3. Get the specified structure
@Test public void test() throws Exception { //Gets the object of the runtime class // Person person = Person.class.getDeclaredConstructor().newInstance(); Class aClass = Person.class; Person o = (Person) aClass.newInstance(); //Gets the specified property Field id = aClass.getField("age"); //year get static properties Field year = aClass.getDeclaredField("year"); /* Sets the value of the current property set():Parameter 1: indicates to set the property of that object. Parameter 2: how much to set this property value setAccessible(true);Ensure that the current property is accessible */ year.setAccessible(true); year.set(null,2021); id.set(o,100111); /* Gets the value of the current property get():Parameter 1: get the current property value of that object */ int o1 = (int) id.get(o); System.out.println(o1); System.out.println(year.get(null)); } /* How to manipulate specified properties in a runtime class* */ @Test public void test2() throws Exception { Class personClass = Person.class; //Gets the object of the runtime class Object o = personClass.newInstance(); //Getdeclaraedfield (string fieldname): get the property of the specified variable name in the runtime class Field field = personClass.getDeclaredField("sex"); //Ensure that the current property is accessible when field.setAccessible(true); //Gets or sets the value of this property of the specified object field.set(o,"male"); Object o1 = field.get(o); System.out.println(o1); } /* How to manipulate a specified method in a runtime class* */ @Test public void test3() throws Exception { Class personClass = Person.class; //Gets the object of the runtime class Person p = (Person) personClass.newInstance(); /* Gets the specified method getDeclaredMethod(): Parameter 1: get the method name of the specified method parameter 2: list of formal parameters in the specified method. */ Method show = personClass.getDeclaredMethod("getCH", String.class); //Ensure that the current method is accessible show.setAccessible(true); /* Call invoke (): parameter 1: the caller of the method (the object of the runtime class), and parameter 2 assigns a value to the formal parameter of the method. invoke The return value of the method is the return value of the calling method in the corresponding class. */ Object invoke = show.invoke(p, "China"); System.out.println(invoke); System.out.println("-----—Call static methods -——————————"); // public static void LXD() Method lxd = personClass.getDeclaredMethod("LXD"); lxd.setAccessible(true); //The invoke() method has a return value. If there is no return value in the method of the called runtime class, null will be returned // Object invoke1 = lxd.invoke(Person.class); Object invoke1 = lxd.invoke(null); System.out.println(invoke1);//null
5. Agent mode and dynamic agent
Principle of agent design pattern:
Wrap the object with a proxy object and replace the original object with the proxy object. Any call to the original object is made through a proxy. The proxy object determines whether and when method calls are transferred to the original object.
I explained the operation of the proxy mechanism before. It belongs to static proxy. The characteristic is that the proxy class and the class of the target object are determined during compilation, which is not conducive to the expansion of the program. At the same time, each agent class can only serve one interface, so there must be too many agents in program development. It is best to complete all proxy functions through a proxy class.
Dynamic proxy refers to the method that the client calls other objects through the proxy class, and it is the proxy object that dynamically creates the target class when the program runs.
Dynamic proxy usage:
debugging
Remote method call
Advantages of dynamic agents over static agents:
All methods declared in the abstract role (Interface) are transferred to a centralized method of the calling processor. In this way, we can deal with many methods more flexibly and uniformly.
5.1 examples of static agents:
interface ClothFactory { public void produceCloth(); } //proxy class class ProxyClothFactory implements ClothFactory{ private ClothFactory Cloth; public ProxyClothFactory(ClothFactory Cloth){ this.Cloth = Cloth; } @Override public void produceCloth() { System.out.println("I'm an agent and do some preparatory work"); Cloth.produceCloth(); System.out.println("The proxy class completes the proxy operation"); } } //Proxy class class ProxyPerson implements ClothFactory{ @Override public void produceCloth() { System.out.println("I'm a surrogate,"); } } public class StaticDaiLiTest { public static void main(String[] args) { //Create proxied class object ProxyPerson p = new ProxyPerson(); //Create proxy class object ProxyClothFactory factory = new ProxyClothFactory(p); factory.produceCloth(); } }
5.2 dynamic agent example
package DaiLi; /* Dynamic agent */ import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; interface Human{ public String getBelief(); void eat(String food); } //Proxy class class SuperMan implements Human{ @Override public String getBelief() { return "I am No: 1"; } @Override public void eat(String food) { System.out.println("I love eating"+food); } } /* What problems need to be solved in order to implement dynamic agent? Question 1: how to dynamically create a proxy class and its object according to the proxy class loaded into memory Question 2: when method A is called through the object of the proxy class, how to dynamically call method A with the same name in the proxy class. */ class ProxyFactory{ //Call this method to return an object of a proxy class. Solve problem 1 public static Object getProxyInstance(Object obj){//obj: object of the proxied class MyInvocationHandler handler = new MyInvocationHandler(); handler.bind(obj); return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler); } } class MyInvocationHandler implements InvocationHandler{ private Object obj;//You need to use the proxied object for assignment public void bind(Object obj){ this.obj = obj; } //When we call method a through the object of the proxy class, we will automatically call the following method: invoke() //The function of method a to be executed by the proxy class is declared in invoke() @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //Method: the method called for the proxy class object. This method is also used as the method to be called by the proxy class object //obj: object of the proxied class Object returnValue = method.invoke(obj, args); //The return value of the proxy class method is the return value of the invoke method in the current class. return returnValue; } } public class RunDaiLiTest { public static void main(String[] args) { SuperMan sup = new SuperMan(); //proxyInstance; Object of proxy class Human proxyInstance = (Human) ProxyFactory.getProxyInstance(sup); //When a method is called through a proxy class object, the method with the same name in the proxy class will be called automatically System.out.println(proxyInstance.getBelief()); proxyInstance.eat("Tomatoes"); System.out.println("***************"); ProxyPerson proxyPerson = new ProxyPerson(); ClothFactory proxyInstance1 = (ClothFactory) ProxyFactory.getProxyInstance(proxyPerson); proxyInstance1.produceCloth(); } }
5.3AOP
It is difficult to see the advantages of this dynamic Proxy in the Proxy and InvocationHandler described above. A more practical dynamic Proxy mechanism is introduced below
- Improved description: code segment 1, code segment 2, code segment 3 and dark code segment are separated, but code segments 1, 2 and 3 are coupled with A specific method A! The most ideal effect is that code blocks 1, 2 and 3 can execute method A without directly calling the method of dark code in the way of hard coding in the program.
- When using Proxy to generate a dynamic Proxy, it often does not generate a dynamic Proxy out of thin air, which is of little significance. Usually, a dynamic Proxy is generated for the specified target object
- This dynamic agent is called AOP agent in AOP. AOP agent can replace the target object. AOP agent contains all the methods of the target object. However, there are differences between the methods in the AOP proxy and the methods of the target object: the methods in the AOP proxy can insert some general processing before and after the execution of the target method.
Illustration
Example 1:
package DaiLi; /* Dynamic agent */ import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; interface Human{ public String getBelief(); void eat(String food); } //Proxy class class SuperMan implements Human{ @Override public String getBelief() { return "I am No: 1"; } @Override public void eat(String food) { System.out.println("I love eating"+food); } } //Dynamic agent AOP pattern example class HumanUtil{ public void method1(){ System.out.println("---------General method 1——————————————————"); } public void method2(){ System.out.println("---------General method 2——————————————————"); } } /* What problems need to be solved in order to implement dynamic agent? Question 1: how to dynamically create a proxy class and its object according to the proxy class loaded into memory Question 2: when method A is called through the object of the proxy class, how to dynamically call method A with the same name in the proxy class. */ class ProxyFactory{ //Call this method to return an object of a proxy class. Solve problem 1 public static Object getProxyInstance(Object obj){//obj: object of the proxied class MyInvocationHandler handler = new MyInvocationHandler(); handler.bind(obj); return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler); } } class MyInvocationHandler implements InvocationHandler{ private Object obj;//You need to use the proxied object for assignment public void bind(Object obj){ this.obj = obj; } //When we call method a through the object of the proxy class, we will automatically call the following method: invoke() //The function of method a to be executed by the proxy class is declared in invoke() @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //Dynamic agent AOP pattern example HumanUtil hum = new HumanUtil(); hum.method1(); //Method: the method called for the proxy class object. This method is also used as the method to be called by the proxy class object //obj: object of the proxied class Object returnValue = method.invoke(obj, args); //Dynamic agent AOP pattern example hum.method2(); //The return value of the proxy class method is the return value of the invoke method in the current class. return returnValue; } } public class RunDaiLiTest { public static void main(String[] args) { SuperMan sup = new SuperMan(); //proxyInstance; Object of proxy class Human proxyInstance = (Human) ProxyFactory.getProxyInstance(sup); //When a method is called through a proxy class object, the method with the same name in the proxy class will be called automatically System.out.println(proxyInstance.getBelief()); proxyInstance.eat("Tomatoes"); System.out.println("***************"); ProxyPerson proxyPerson = new ProxyPerson(); ClothFactory proxyInstance1 = (ClothFactory) ProxyFactory.getProxyInstance(proxyPerson); proxyInstance1.produceCloth(); } }