Basic articles: In-depth analysis of JAVA reflection mechanism

The concept of reflection

  • Java's radiation mechanism: When the program is running, the program has the ability to obtain all the methods and attributes of a class; and for any object, you can call any of its methods or obtain its attributes
  • Popular analysis: java files need to be compiled into .class files to be loaded and used by jvm. The .class data of the object is Class<T> in jvm; if we can get this Class<T> object, we can get the Class<T > Corresponding object type, and the method and attribute value declared in the type; you can also create the corresponding type object according to Class<T>, and manipulate the object in turn through Field and Method
  • Introduction to java related classes
Class name description
Class<T> An entity representing a class, representing a class or interface in a running Java application
Field Class member variables (member variables are also called class attributes)
Method Class method
Constructor<T> Class construction method

Three ways to get Class

  • 1 Get class by known type
// 根据Example 获取Class =》Example.class
public Class<Example> getExample(){
    
    
    Class<Example> clazz = Example.class;
    return clazz;
}
  • 2Get class through instance object
public Class<Example> getExampleByInstance(){
    
    
    Example example = new Example();
    // getClass是Object类里面的方法;《?》 是通配符
    Class<?> clazz = example.getClass();
    return (Class<Example>)clazz;
}
  • 3 Get the class with the specified class name in the full path through Class.forName
/** forName0 本地方法,C++实现,jvm调用
 *	1 className 是个类名  2 initialize 是否延迟加载  3 loader 加载器
 */
private static native Class<?> forName0(String className, boolean initialize,
				ClassLoader loader, Class<?> caller) throws ClassNotFoundException;

public static Class<?> forName(String className) throws ClassNotFoundException {
    
    
        Class<?> caller = Reflection.getCallerClass();
        return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
    }
// 两个forName方法最终都会调用forName0方法去加载class   
public static Class<?> forName(String name,
		boolean initialize, ClassLoader loader) throws ClassNotFoundException {
    
    
        ....
        return forName0(name, initialize, loader, caller);
    }
// 示例:通过java.lang.Integer 
public Class<Integer> getInteger()throws ClassNotFoundException{
    
    
    Class<?> clazz = Class.forName("java.lang.Integer");
    return (Class<Integer>)clazz;
}

JAVA reflection API

  • Class common operation method
//获取所有的构造方法 / private public
public Constructor<?>[] getDeclaredConstructors()
//获取特定的构造方法 / private public
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)    
//获取类的父类
public native Class<? super T> getSuperclass()    
//获取类实现的接口
private Class<?>[] getInterfaces(boolean cloneArray)  
//获取在类内定义的内部类或接口
public Class<?>[] getDeclaredClasses()
//获取所有的方法
public Method[] getDeclaredMethods() throws SecurityException
//根据方法名和参数获得特定的方法
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)  
//获取类型的定义的所有属性
public Field[] getFields() throws SecurityException
// 根据属性命名获得特定的Field
public Field getField(String name) 
  • Method commonly used operation method
//获得方法的放回类型
public Class<?> getReturnType()   
//获得方法的传入参数类型
public Class<?>[] getParameterTypes()   
//obj是实例对象,args是方法,反过来由Method控制对象的方法调用
public Object invoke(Object obj, Object... args)
  • Common operating methods of Field
//属性与obj相等则返回true
public boolean equals(Object obj)
//获得obj中对应的属性值
public Object get(Object obj)
//设置obj中对应属性值
public void set(Object obj, Object value) 
  • Constructor
//根据传递的参数创建类的对象:initargs 构造方法参数
public T newInstance(Object... initargs) 
  • 1 Create objects based on class
//方式一 clazz.newInstance()
Class<Example> clazz = Example.class;
Example example = clazz.newInstance();
//方式二 先获取再由Constructor:clazz.getConstructors()/getConstructor(...) 
//再由Constructor.newInstance 方法构造对象
-----------------------------------------
public class Example {
    
    
    private int value;
    public Example(){
    
     } // 如果只声明有参构造函数,clazz.newInstance()会报错
    public Example(Integer value){
    
      this.value  = value;  }
    static public void main(String[] args) throws Exception{
    
    
        Class<Example> clazz = Example.class;
        //根据指定构造函数参数获取Constructor
        Constructor<Example> constructor = clazz.getConstructor(Integer.class);
        Example example = constructor.newInstance(100);
        System.out.println(example.value);
    }
}    
  • 2 Obtain the Field from the class and manipulate the attributes of the instance
public class Example {
    
    
    private int value , count;
    static public void main(String[] args) throws Exception{
    
    
        Class<Example> clazz = Example.class;
        //获取所有的属性,getField只能获取public的属性
		Field[] fs = clazz.getDeclaredFields();
        //根据名称获取指定 Field
        Field value = clazz.getDeclaredField("value");
        Example example = clazz.newInstance();
        //使用反射机制可以打破封装性,导致了java对象的属性不安全  
        value.setAccessible(true); //setAccessible(true)让private的参数可赋值操作
        //由Field反过去设置example的值
        value.set(example,100);
        System.out.println(example.value);
    }
}
  • 3 Get Method by class and call instance method by reflection
public class Example {
    
    
    public static void main(String[] args) throws Exception {
    
    
        Class<Example> clazz = Example.class;
        Example example = clazz.newInstance();
        Method[] methods = clazz.getDeclaredMethods();
        //getDeclaredMethod和getMethod是:getMethod只能返回public的方法
        Method method = clazz.getDeclaredMethod("hello", String.class);
        method.setAccessible(true);
        method.invoke(example, "cscw");
    }
    private void hello(String name) {
    
     System.out.println(name + " Hello!"); }
}
-----
cscw Hello!

Application scenarios of reflection mechanism

  • 1 Dynamic expansion: It is assumed that there is the same group of classes that implement the same interface, and the loading method of the class is not limited. When we need the function that a specific class implements, just load the .class file and get the corresponding Class<T> object. The object instance can be instantiated by Class or Constructor; according to the interface definition, a certain method in Class<T> can be obtained, and the function method can be called with instance
  • 2 Spring's IOC is based on the reflection mechanism
  • 3 Dynamic proxy of JDK

Reflection and JDK dynamic proxy

  • A Proxy class and an InvocationHandler interface are provided under the java.lang.reflect package of Java. JDK dynamic proxy class or dynamic proxy object can be generated through this class and interface
public interface InvocationHandler {
    
    
	//所有方法都会调用此代理方法
    Object invoke(Object var1, Method var2, Object[] var3) throws Throwable;
}	 
public class Proxy implements Serializable...
    //根据interfaces和InvocationHandler生成代理对象
    public static Object newProxyInstance(ClassLoader loader,
    		Class<?>[] interfaces, InvocationHandler h) 
    ...    
  • The dynamic proxy of JDK is implemented by Proxy and InvocationHandler; the proxy object must implement an interface. The proxy object is generated by the Proxy and can be converted to the implementation class object OBJ of the interface interface. When the OBJ method is called, InvocationHandler.invoke will be triggered, and the parameters are the proxy object , the Method object , and the parameters required by the method in turn . You can add extended logic to the invoke method, such as logging operations; and you can use reflection technology to call the proxy object method in the invoke method
  • Example
public class ExampleFactory<T> implements InvocationHandler{
    
    
    private T target;
    public T bind(T obj){
    
    
        target = obj;
        return (T)Proxy.newProxyInstance(obj.getClass().getClassLoader(),
        			obj.getClass().getInterfaces(),this);
    }
    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
    
    
        //增强逻辑
        System.out.println("log start");
        //反射调用被代理对象方法
        Object result = method.invoke(target,objects);
        System.out.println("log end");
        return result;
    }
}
-----------
public interface Face {
    
    
    void hello(String name);
}
---------
//被代理对象必须实现一个接口,并由接口方法对方提供功能
public class Example implements Face {
    
    
	public void hello(String name) {
    
    
        System.out.println(name + " Hello!");
    }
    public static void main(String[] args)  {
    
    
    	//ExampleFactory<Face> 相当于一个中介人
        ExampleFactory<Face> exampleProxy= new ExampleFactory<>();
        //example 是代理对象
        Face example = exampleProxy.bind(new Example());
        example.hello("思婷");
    }
}
-----
log start
思婷 Hello!
log end

Welcome refers to the error in the text

Follow the public account and communicate together

Reference article

Guess you like

Origin blog.csdn.net/u013591094/article/details/108821958