zoukankan      html  css  js  c++  java
  • java魔法类之ReflectionFactory介绍

    前言

    在看objenesis(一个提供多种实例化对象的方式的库)的源码时,发现其中使用到了ReflectionFactory类,通过它可以绕过构造器来实例化对象。

    简单使用

    定义一个包含有参构造器的类

    public class User {
    
      private String name;
    
      public User(String name) {
        System.out.println("User.Constructor");
      }
    
      @Override
      public String toString() {
        return "User.toString()";
      }
    }
    

    使用反射实例化对象

    import java.lang.reflect.Constructor;
    
    public class TestReflection {
    
      public static void main(String[] args) throws Exception {
        Constructor<User> declaredConstructor = User.class.getDeclaredConstructor();
        System.out.println(declaredConstructor.newInstance());
      }
    
    }
    

    会报错,因为没有无参的构造器

    Exception in thread "main" java.lang.NoSuchMethodException: com.imooc.sourcecode.java.objenesis.test1.User.<init>()
    	at java.base/java.lang.Class.getConstructor0(Class.java:3350)
    	at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2554)
    	at com.imooc.sourcecode.java.objenesis.test1.TestReflection.main(TestReflection.java:9)
    

    使用ReflectionFactory实例化对象

    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    import sun.reflect.ReflectionFactory;
    
    public class TestReflectionFactory {
    
      public static void main(String[] args)
          throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取ReflectionFactory对象,它本身是单例的
        ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory();
        //获取Object类的构造器
        Constructor<Object> constructor = Object.class.getDeclaredConstructor();
        //根据Object构造器创建一个User类的构造器
        Constructor<?> constructorForSerialization = reflectionFactory
            .newConstructorForSerialization(User.class, constructor);
        constructorForSerialization.setAccessible(true);
        //实例化对象
        System.out.println(constructorForSerialization.newInstance());
      }
    
    }
    

    输出结果为

    User.toString()
    

    可以看到正常实例化了对象并且没有执行构造器。

    实现原理

    内部使用字节码创建ConstructorAccessor接口的实现类

    public final Constructor<?> newConstructorForSerialization(Class<?> cl,
                                                                   Constructor<?> constructorToCall)
        {
            if (constructorToCall.getDeclaringClass() == cl) {
                constructorToCall.setAccessible(true);
                return constructorToCall;
            }
            return generateConstructor(cl, constructorToCall);
        }
    
    // 创建构造器
    private final Constructor<?> generateConstructor(Class<?> cl,
                                                         Constructor<?> constructorToCall) {
    
    	//核心逻辑,通过字节码生成ConstructorAccessor,实现类类型为SerializationConstructorAccessorImpl 
            ConstructorAccessor acc = new MethodAccessorGenerator().
                generateSerializationConstructor(cl,
                                                 constructorToCall.getParameterTypes(),
                                                 constructorToCall.getExceptionTypes(),
                                                 constructorToCall.getModifiers(),
                                                 constructorToCall.getDeclaringClass());
            Constructor<?> c = newConstructor(constructorToCall.getDeclaringClass(),
                                              constructorToCall.getParameterTypes(),
                                              constructorToCall.getExceptionTypes(),
                                              constructorToCall.getModifiers(),
                                              langReflectAccess().
                                              getConstructorSlot(constructorToCall),
                                              langReflectAccess().
                                              getConstructorSignature(constructorToCall),
                                              langReflectAccess().
                                              getConstructorAnnotations(constructorToCall),
                                              langReflectAccess().
                                              getConstructorParameterAnnotations(constructorToCall));
            setConstructorAccessor(c, acc);
            c.setAccessible(true);
            return c;
        }
    

    生成字节码的核心为MethodAccessorGenerator的generateSerializationConstructor()方法。

    参考

    objenesis官网
    reflectionFactory.newConstructorForSerialization原理

  • 相关阅读:
    HDU 1863 畅通工程(Kruskal)
    HDU 1879 继续畅通工程(Kruskra)
    HDU 1102 Constructing Roads(Kruskal)
    POJ 3150 Cellular Automaton(矩阵快速幂)
    POJ 3070 Fibonacci(矩阵快速幂)
    ZOJ 1648 Circuit Board(计算几何)
    ZOJ 3498 Javabeans
    ZOJ 3490 String Successor(模拟)
    Java实现 LeetCode 749 隔离病毒(DFS嵌套)
    Java实现 LeetCode 749 隔离病毒(DFS嵌套)
  • 原文地址:https://www.cnblogs.com/strongmore/p/15470175.html
Copyright © 2011-2022 走看看