Overview of reflection Mechanism

Reflection is the key to dynamic languages. Reflection allows programs to use the Reflection API to retrieve internal information of any class during execution and to directly manipulate internal properties and methods of an object. After the Class is loaded, the method area in the heap produces an object of type Class (each Class has only one Class object), which contains the complete structure information of the Class. We can see the structure of the class through this object. This object is like a mirror through which you can see the structure of the class, so we call it a reflection.The main API for reflectionGet the four structures of the Class Class:

  1. Invoke properties of the runtime class

Class clazz1 = Person.class; System.out.prinln(clazz1);

2. Call getClass() Person p1 = new Person() from the object of the runtime class; Class clazz2 = p1.getClass(); System.out.println(clazz2); ForName (String classPath) Class clazz3 = class.forname (” java.lang.string “); System.out.println(clazz3); 4. Use the class loader: this this this = ReflectionTest. Class. GetClassLoader (); Class clazz4 = classLoader.loadClass(“com.atguigu.java.Person”); System.out.println(clazz4);

Understand the Class Class and get the Class instance

Prior to reflection, an internal private structure of the Person class cannot be called from an object outside of a class. (for example, name, showNation(), and private constructors).General action on Person after reflection:With reflection, you can invoke the private constructor, private properties, and private methods of the Person class.

  1. Invoke the private constructor

Constructor cons1 = clazzz.getDeclaredConstructor(String.class); cons1.setAccessible(true); Person p1 = (Person) cons1.newInstance(“jerry”); Person p1 = (Person) cons1.newInstance(“jerry”); System.out.println(p1); Clazz.getdeclaredfield (“name”); name.setAccessible(true); name.set(p1,”HanMeimei”); System.out.prinln(p1); Clazz.getdeclaredmethod (“showNation”, string.class); showNamtion.setAccessible(true); ShowNation. Invoke (p1, “China”); // Execute the private String Nation = (String) showNation. Invoke (p1, “China “); // System.out.prinln(nation); Related questions?

  1. Common constructs can be called either by direct new or reflection. Which one is used in development?

Suggestion: Use new and when to use reflection: When we are not sure which class object to build during compilation, we need to use reflection 2. Whether reflection and encapsulation contradict each other

Class loading and the understanding of ClassLoader

  1. Class loading process:

The program generates one or more bytecode files (ending in.class) after passing through the java.exec command. We then run an interpretation of a bytecode file using the java.exe command. This is equivalent to loading a bytecode file into memory. This process is called class loading. A Class loaded into memory is called a runtime Class, and the runtime Class acts as an instance of Class. An instance of Class corresponds to a runtime Class. 3. The runtime Class is loaded into memory and cached for a certain amount of time. During this time, we can get the runtime class in different ways

What is a class loader

Three types of loaders:Common methods of reading configuration files:Use the system class loader to read the configuration file

Objects that create run-time classes through reflection

Class clazz = Person.class; Person obj = (Person)clazz.newInstance();

Gets the complete structure of the runtime class

Get class attributes:

Class clazz = Person.class;
Field[] fields =  clazz.getFields();    // Public attributes defined in the current class and its parent class can be obtained
Field[] declaredFields = clazz.getDeclaredFields();  // Get all the attributes defined in the current classGet the inner structure of a class attribute:for(Field f: declaredFields){Get permission modifier for class attributesintmodifier = f.getModifiers(); System.out.print(Modifier.toString(modifier)); Get the data type of the Class attribute Class type = f.getType(); System.out.println(type.getName()); String fName = f.getName(); System.out.print(fName); } Class clazz = person.class; Method[] methods = clazz.getMethods();// We can get public methods defined in the current class and its parent class
Method[] methods = clazz.getDeclaredMethods(); // Get all methods defined in the current classAnnotation[] annos = m.annotations (); Annotation[] annos = m.annotations ();for(){sout(a)); Get permission modifiers: System.out.print(Modifier. ToString (m.getModifiers())); Print (m.getreturnType ().getName()); Get the list of parameters: Class[] parameterTypes = m.geetparametertypes ();if(! (parameterTypes ==null || parameterTyupes.length ==0)) {for(Class P :parameterTypes){system.out.print (p.get_name)}} Class[] exceptionTypes = m.get_ExceptionTypes ();if(! (exceptionTypes ==null || exceptionTypes.length ==0)) {for(Class p:exception  Types){
         System.out.print(p.getName)
         }
     }
Copy the code

Gets the runtime class constructor structure

Class clazz = Person.class;
Constructor[] construcotrs = clazz.getConstructors();      // Gets the constructor declared public in the current runtime class
for(Constructor c : constructors){
 System.out.println(c);
 }
Constructor[] construcotrs = clazz.getDeclaredConstructors();      // Get all the constructors in the current runtime class
for(Constructor c : constructors){
 System.out.println(c);
 }
Copy the code

Get the type of run-time class parent and parent (functional vs. logical code)

// Get the parent of the runtime class
Class clazz = Person.class;
Class superclass = clazz.getSuperclass();
System.out.println(superclass);
// Get the run-time class's generic parent
Class clazz = Person.class;
Type genericSuperclass = clazz.getGenericSuperclass();
System.out.println(superclass);
// Get the generics of the run-time class with its generic parent
 Class clazz = Person.class;
 Type genericSuperclass = clazz.getGenericSuperclass();
 ParameterizedType paramType = (ParameterizedType) genericSuperclass;
 Type[] actualTypeArguments = paramType.getActualTypeArguments(); // A generic type like Map takes two arguments: Map
      ,v>
 System.out.println(genericSuperclassj[0]o.getTypeName());
Copy the code

Gets the interface implemented by the runtime class

Class clazz = Person.class;
Class[] interfaces = clazz.getInterfaces();
Class[] interfaces1 = clazz.getSuperclass.getInterfaces(); // Get the parent's interface
for(Class c: interfaces){
System.out.println(c);
} 
Copy the code

Gets the package in which the runtime class resides

Class clazz = Person.class;
Package pack = clazz.getPackage();
System.out.prinln(pack);
Copy the code

Gets an annotation for the runtime class declaration

Class clazz = Person.class;
Annotation[] annotaions = clazz.getAnnotations();
for(Annotation annos: annotations){
 System.out.println(annos);
 }
Copy the code

Invoke the specified structure of the runtime class (important)

Gets and manipulates the properties specified by the runtime class

Class clazz = Person.class; Person p = clazz.newinstance (); Field id = clazz.getField(“id”); Field id = clazz.getDeclaredField(“id”); id.setAccessible(true); // set the value of the current attribute id.set(p,1001); Int pid = (int)id.get(p);

Get and manipulate methods specified in the runtime class (mastery)

Class clazz = Person.class; Person p = (Person) clazz.newInstance(); Method show = clazz.getDecalaredMethod(“show”,String.class); // Parameter 1: gets the name of the specified method, parameter 2: indicates the list of parameters to get the method show.setaccessible (true); Show.invoke (p,”CHN”) // Parameter 1: method caller parameter 2: The argument assigned to the Method parameter String nation = (String) show.invoke(p,”CHN”) // call a Method with a return value // Call a static Method Call a static Method without instantiating Method showStatic = clazz.getDeclaredMethod(“showStatic”); showStatic.setAccessible(true); Object returnVal = showStatic.invoke(Person.class); Prinln (returnVal); // Null in parentheses is ok, because the static methods of each object are the same: system.out.prinln (returnVal); //null Returns null if void is used

Gets and manipulates the constructor specified in the runtime class (uncommon, common newInstance)

Class clazz = Peson.class; Constructor cons = clazz.getDeclaredConstructor(String.class); cons.setAccessible(true); Person per = (Person) cons.newInstance(“Tom”); System.out.println(per);

Application of Reflection: Dynamic Proxy AOP(Aspect Orient Proxy) (more on this in Sprint)

Static agent

// Factory interface: what the proxy class needs the proxy to do
interface ClothFactory{
    void produceCloth(a);
}
/ / the proxy class
class ProxyClothFactory implements ClothFactory{
    private ClothFactory factory;
    public ProxyClothFactory(ClothFactory factory){
        this.factory = factory;    // Create an object of the proxied class
    }
    @Override
    public void produceCloth(a) {
        System.out.println("Preparation of the agency factory");
        // What is done by the proxy class
        factory.produceCloth();
        System.out.println("Follow-up work done on behalf of the factory"); }}// Proxy class
class NikeClothFactory implements ClothFactory{
    public void produceCloth(a){
        System.out.println("Nike makes a batch of sportswear."); }}public class StaticProxyTest {
    public static void main(String[] argv){
        // Create an object of the proxied class
        ClothFactory nike = new NikeClothFactory();
        // Create a proxy object
        ClothFactory proxyFactory = newProxyClothFactory(nike); proxyFactory.produceCloth(); }}Copy the code

A dynamic proxy

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
// The proxied class needs what the proxied class needs to do
interface Human{
    String getBelief(a);
    void eat(String food);
}
// Proxy class
class SuperMan implements Human{
    @Override
    public String getBelief(a){
        return "I believe I can fly";
    }
    @Override
    public void eat(String food){
        System.out.println("I like to eat."+ food); }}/ / the problem:
// 1. How to dynamically create a proxy class and its object based on the proxy class loaded into memory?
// 2. How to dynamically call a method of the same name in the propped class when calling an object of the propped class?
// Create a proxy object
class ProxyFactory{
    // obj is the proxied class
    public static Object getProxyInstance(Object obj){
        MyInvocationHandler handler = new MyInvocationHandler();
        handler.bind(obj);
        // Create a proxy class object: parameter 1: get the class loader of obj class, parameter 2: get the interface implemented by obj, parameter 3: get the method called in obj
        returnProxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler); }}class MyInvocationHandler implements InvocationHandler{
    private Object obj;
    // Bind the proxied class
    public void bind(Object obj){
        this.obj = obj;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // Invoke methods in the proxied class: method is reflected
        HumanUti1 util1 = new HumanUti1();
        HumanUtil2 util2 = new HumanUtil2();
        util1.method1();
        Object returnValue = method.invoke(obj,args);
        util2.method2();
        returnreturnValue; }}// Call the generic method:
class HumanUti1{
    public void method1(a){
        System.out.println("------- General method 1-------"); }}class HumanUtil2{
    public void method2(a){
        System.out.println("----- General method 2---------"); }}public class ProxyTest {
    public static void main(String[] args) {
        SuperMan superMan = new SuperMan();
        // Instantiate the dynamic proxy class
        Human proxyInstance = (Human)ProxyFactory.getProxyInstance(superMan);
        // When a method is called from a proxy class object, the method is called from the propped class
        String belief = proxyInstance.getBelief();
        System.out.println(belief);
        proxyInstance.eat("Chicken legs");
        // Proxy class dynamic:
        NikeClothFactory nikeClothFactory = newNikeClothFactory(); ClothFactory proxyClothFactory = (ClothFactory)ProxyFactory.getProxyInstance(nikeClothFactory); proxyClothFactory.produceCloth(); }}Copy the code

Dynamic Proxy review:Examples of static proxies:Disadvantages of static proxies:Dynamic proxy features:Dynamic proxy implementation:

  1. How to dynamically create a Proxy class and its object from proxy.newProxyInstance () loaded into memory
  2. Invoke (); invoke(); Invoke (); invoke(); invoke()