当前位置: 首页 > news >正文

java基础:反射

        在 Java 中,只要给定类的名字,就可以通过反射机制来获得类的所有信息,而这个类在编译过程中甚至是还未存在的。在运行的时候我们可以通过配置文件获取某个类的类名,然后使用反射机制构造这个类的对象,调用这个对象的方法,修改这个对象的成员变量。

1. 编译期和运行期

  • 编译期:是指把源码交给编译器编译成计算机可以执行的文件的过程。在 Java 中也就是把 Java 代码编成 class 文件的过程。编译期只是做了一些翻译功能,并没有把代码放在内存中运行起来,而只是把代码当成文本进行操作,比如检查错误。
  • 运行期:是把编译后的文件交给计算机执行,直到程序运行结束。运行期就把在磁盘中的代码放到内存中执行起来。

2. 反射机制

        java执行编译的时候将java文件编译成字节码class文件,类加载器在类加载阶段将class文件加载到内存,并实例化一个java.lang.Class的对象。万事万物皆对象,Class被称为类对象,描述类在元数据空间的数据结构,包含类中定义的属性、方法、构造方法、注解、接口等信息。

        当我们刚接触java语言的时候,我们最常写的代码应该就是初始化某个对象,然后调用该对象的方法。例如:

User user = new User();
user.getName();

        当我们想在运行期才能指定具体对象的类型或调用的某个方法、属性时,普通的编码方式将无法实现需求。

        Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。

        在 Java 中,只要给定类的名字,就可以通过反射机制来获得类的所有信息,而这个类在编译过程中甚至是还未存在的。在运行的时候我们可以通过配置文件获取某个类的类名,然后使用反射机制构造这个类的对象,调用这个对象的方法,修改这个对象的成员变量。

        反射机制很重要的一点就是“运行时”,其使得我们可以在程序运行时加载、探索以及使用编译期间完全未知的 .class 文件。换句话说 Java 程序可以加载一个运行时才得知名称的 .class 文件,然后获悉其完整构造,并生成其对象实体、或对其 fields(变量)设值、或调用其 methods(方法)。一般情况下,我们使用某个类时必定知道它是什么类,是用来做什么的。于是我们直接对这个类进行实例化,之后使用这个类对象进行操作。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。

3. 原理解析

        Java反射机制的原理主要是通过Class类来实现的。Class类是Java中反射机制的核心类,它可以在运行时动态地获取一个类的信息。使用Class.forName()方法获取Class对象,

Class.forName()方法接受一个字符串参数,该参数为完整类名,它将返回该类的Class对象。

Class<?> clazz = Class.forName("jvm.newInstance.NewInstanceDto");
//通过反射获取有参构造函数
//Class源码 public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes);Constructor<?> c1 = clazz.getDeclaredConstructor()
//反射方式获取方法
//Class源码 public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
Method m1 = clazz.getDeclaredMethod()
//反射方式获取属性字段
//Class源码 public Field getDeclaredField(String name)Field f1 = clazz.getDeclaredField();
//反射方式调用方法结果
// Method 源码:  public Object invoke(Object obj, Object... args)m1.invoke()

3.1. Constructor.newInstance 源代码解读

结论:当首次执行Constructor.newInstance()方法时,会通过reflectionFactory.newConstructorAccessor()在不同条件下选择合适的ConstructorAccessor实现,并对返回的实现进行缓存,便于复用。

  • 抽象类、Class类: 底层实现抛出InstantiationException 异常。
  • ConstructorAccessorImpl 的子类: 底层实现抛出InstantiationException 异常。
  • sun.reflect.noInflation 值设置为 ture: 通过字节码生成技术MethodAccessorGenerator.generateConstructor()(例如使用ASM库)生成一个新的 ConstructorAccessor 实现。实现类包含 newInstance方法,该方法直接调用目标待实例化对象的构造函数。可以在运行时高效地创建对象实例
  • sun.reflect.noInflation 值设置为 false: 返回 代理类DelegatingConstructorAccessorImpl

        而DelegatingConstructorAccessorImpl(代理类)对象对NativeConstructorAccessorImpl(Native 实现方式类)进行了代理,Constructor.newInstance()在调用时候,实际执行的是NativeConstructorAccessorImpl.newInstance()方法。

  NativeConstructorAccessorImpl.newInstance()方法在执行时,通过属性numInvocations计数,当调用次数超过一定次数, 通过字节码生成技术MethodAccessorGenerator.generateConstructor()(例如使用ASM库)生成一个新的 ConstructorAccessor 实现。 NativeConstructorAccessorImpl 对象通过自身持有的parent 属性执行parent.setDelegate(acc)操作,对DelegatingConstructorAccessorImpl对象的代理对象进行切换,后续方法执行底层方式切换为新的 ConstructorAccessor 实现。

3.1.1. Constructor.newInstance

public T newInstance(Object ... initargs)throws InstantiationException, IllegalAccessException,IllegalArgumentException, InvocationTargetException{// 安全性权限校验if (!override) {// 快速检查成员访问权限if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {Class<?> caller = Reflection.getCallerClass();//检查访问权限checkAccess(caller, clazz, null, modifiers);}}//是否为枚举类型。不允许通过反射创建枚举对象,有助于保持枚举的完整性if ((clazz.getModifiers() & Modifier.ENUM) != 0)throw new IllegalArgumentException("Cannot reflectively create enum objects");ConstructorAccessor ca = constructorAccessor;   // read volatileif (ca == null) {ca = acquireConstructorAccessor();}@SuppressWarnings("unchecked")T inst = (T) ca.newInstance(initargs);return inst;
}
//获取实现private ConstructorAccessor acquireConstructorAccessor() {// 第一步:检查是否已有实现。若有则返回,缓存机制。ConstructorAccessor tmp = null;if (root != null) tmp = root.getConstructorAccessor();if (tmp != null) {constructorAccessor = tmp;} else {// 没有则通过reflectionFactory生成tmp = reflectionFactory.newConstructorAccessor(this);setConstructorAccessor(tmp);}return tmp;
}
//缓存reflectionFactory生成的ConstructorAccessor实现。
void setConstructorAccessor(ConstructorAccessor accessor) {constructorAccessor = accessor;// Propagate upif (root != null) {root.setConstructorAccessor(accessor);}
}

        第一次调用 Constructor.newInstance()时候,会调用reflectionFactory.newConstructorAccessor() 创建一个新的ConstructorAccessor,并赋值给methodAccessor进行缓存。

3.1.2. reflectionFactory.newConstructorAccessor()

public ConstructorAccessor newConstructorAccessor(Constructor<?> c) {//1.检查初始化状态checkInitted();// 获取当前构造器所属的类。Class<?> declaringClass = c.getDeclaringClass();if (Modifier.isAbstract(declaringClass.getModifiers())) {//如果声明类是抽象,最终处理方式抛出InstantiationException异常,因为不能直接实例化抽象类return new InstantiationExceptionConstructorAccessorImpl(null);}if (declaringClass == Class.class) {//声明类是Class类本身,最终处理方式抛出InstantiationException异常,因为不能直接实例化Class类本身return new InstantiationExceptionConstructorAccessorImpl("Can not instantiate java.lang.Class");}//if (Reflection.isSubclassOf(declaringClass,ConstructorAccessorImpl.class)) {//处理ConstructorAccessorImpl 的子类实例化 避免循环引用问题。 return new BootstrapConstructorAccessorImpl(c);}//noInflation 用于控制反射方法访问器的生成策略,以平衡性能和资源消耗。//-通过设置系统属性 sun.reflect.noInflation,开发人员可以在特定情况下优化反射操作的性能。if (noInflation && !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())) {// 生成java实现方式实现类return new MethodAccessorGenerator().generateConstructor(c.getDeclaringClass(),c.getParameterTypes(),c.getExceptionTypes(),c.getModifiers());} else {//生成代理类DelegatingConstructorAccessorImpl实现。NativeConstructorAccessorImpl acc =new NativeConstructorAccessorImpl(c);DelegatingConstructorAccessorImpl res =new DelegatingConstructorAccessorImpl(acc);acc.setParent(res);return res;}
}

   reflectionFactory.newConstructorAccessor()在不同条件下选择合适的ConstructorAccessor实现,以确保能够高效、正确地通过反射创建对象实例:

  • 抽象类、Class类: 返回InstantiationExceptionConstructorAccessorImpl;
  • ConstructorAccessorImpl 的子类: 返回BootstrapConstructorAccessorImpl
  • sun.reflect.noInflation 值设置为 ture: 通过字节码生成技术MethodAccessorGenerator.generateConstructor()(例如使用ASM库)生成一个新的 ConstructorAccessor 实现并返回。
  • sun.reflect.noInflation 值设置为 false: 返回 代理类DelegatingConstructorAccessorImpl 。代理类DelegatingConstructorAccessorImpl与 Native 实现方式类 NativeConstructorAccessorImpl互相持有引用。

3.1.3. InstantiationExceptionConstructorAccessorImpl

class InstantiationExceptionConstructorAccessorImplextends ConstructorAccessorImpl {private final String message;InstantiationExceptionConstructorAccessorImpl(String message) {this.message = message;}public Object newInstance(Object[] args)throws InstantiationException,IllegalArgumentException,InvocationTargetException{if (message == null) {throw new InstantiationException();}throw new InstantiationException(message);}
}

        调用newInstance 抛出new InstantiationException()异常,兼容特殊情况。

3.1.4. BootstrapConstructorAccessorImpl

class BootstrapConstructorAccessorImpl extends ConstructorAccessorImpl {private final Constructor<?> constructor;BootstrapConstructorAccessorImpl(Constructor<?> c) {this.constructor = c;}public Object newInstance(Object[] args) throws IllegalArgumentException, InvocationTargetException{try {return UnsafeFieldAccessorImpl.unsafe.allocateInstance(constructor.getDeclaringClass());} catch (InstantiationException e) {throw new InvocationTargetException(e);}}
}

        底层调用 UnsafeFieldAccessorImpl.unsafe.allocateInstance(constructor.getDeclaringClass());native 本地方法生成目标对象实例。

3.1.5. NativeConstructorAccessorImpl

class DelegatingConstructorAccessorImpl extends ConstructorAccessorImpl {private ConstructorAccessorImpl delegate;DelegatingConstructorAccessorImpl(ConstructorAccessorImpl delegate) {setDelegate(delegate);}public Object newInstance(Object[] args)throws InstantiationException,IllegalArgumentException,InvocationTargetException {return delegate.newInstance(args);}void setDelegate(ConstructorAccessorImpl delegate) {this.delegate = delegate;}
}

   DelegatingConstructorAccessorImpl持有NativeConstructorAccessorImpl引用delegate,并且自身方法invoke()NativeConstructorAccessorImpl.invoke()进行了包装,底层执行的还是NativeConstructorAccessorImpl.invoke()。

3.1.6. DelegatingConstructorAccessorImpl

class NativeConstructorAccessorImpl extends ConstructorAccessorImpl {private final Constructor<?> c;private DelegatingConstructorAccessorImpl parent;private int numInvocations;NativeConstructorAccessorImpl(Constructor<?> c) {this.c = c;}public Object newInstance(Object[] args) throws InstantiationException,IllegalArgumentException,InvocationTargetException{//1.1、numInvocations记录调用次数,//-当调用次数超过ReflectionFactory.inflationThreshold()设定的值且非匿名类,切换ConstructorAccessorImpl实例//1.2、ReflectUtil.isVMAnonymousClass():所属的类是否是虚拟机匿名类(vm-anonymous class)。//-如果是匿名类,不能生成字节码,因为匿名类没有名字,无法在生成的字节码中引用。if (++numInvocations > ReflectionFactory.inflationThreshold()&& !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())) {//1-1、使用 MethodAccessorGenerator 生成一个新的 ConstructorAccessor 实现。ConstructorAccessorImpl acc = (ConstructorAccessorImpl)new MethodAccessorGenerator().generateConstructor(c.getDeclaringClass(),c.getParameterTypes(),c.getExceptionTypes(),c.getModifiers());//1-2、将生成的 ConstructorAccessor 设置为 parent 的代理,后续调用执行新的 ConstructorAccessor 实现。parent.setDelegate(acc);}//2、执行本地方法。return newInstance0(c, args);}void setParent(DelegatingConstructorAccessorImpl parent) {this.parent = parent;}private static native Object newInstance0(Constructor<?> c, Object[] args)throws InstantiationException,IllegalArgumentException,InvocationTargetException;
}

    NativeConstructorAccessorImpl 的主要作用是通过本地方法高效地创建对象实例。通过属性numInvocations计数,当调用次数超过一定次数, 通过字节码生成技术MethodAccessorGenerator.generateConstructor()(例如使用ASM库)生成一个新的 ConstructorAccessor 实现。这个生成的实现是纯Java代码,但经过优化,可以在运行时高效地创建对象实例。 并且通过自身持有的parent 属性parent.setDelegate(acc),对DelegatingConstructorAccessorImpl对象的代理对象进行切换。

3.1.7. NativeConstructorAccessorImpl 与MethodAccessorGenerator.generateConstructor()区别。

  1. 实现方式:
    • NativeConstructorAccessorImpl: 使用本地方法(native method)来创建对象实例,由JVM实现。
    • MethodAccessorGenerator.generateConstructor(): 通过字节码生成技术动态生成一个纯Java的 ConstructorAccessor 实现。
  1. 灵活性
    • NativeConstructorAccessorImpl: 果构造器的签名发生变化,NativeConstructorAccessorImpl 无法动态调整,需要重新生成或选择其他实现。
    • MethodAccessorGenerator.generateConstructor():可以根据具体的构造器参数和异常类型生成最合适的实现。这种灵活性使得它可以适应各种不同的构造器签名。
  1. 性能:
    • NativeConstructorAccessorImpl: 通常在初始调用时性能较好,因为本地方法调用通常比纯Java代码快。频繁调用时开销较大,影响性能(方法查找和动态绑定)。
    • MethodAccessorGenerator.generateConstructor(): 会直接调用目标类的默认构造方法,避免了反射API的开销。初始生成时间较长,在频繁调用时性能更好。
  1. 适用场景:
    • NativeConstructorAccessorImpl: 适用于初始调用和中等频率的调用。
    • MethodAccessorGenerator.generateConstructor(): 适用于高频率的调用,特别是当同一个构造器被频繁调用时。

3.2. Method.invoke 源代码解读

结论:当首次执行Method.invoke()时候,会调用reflectionFactory.newMethodAccessor(this)会根据sun.reflect.noInflation 配置情况, 选择MethodAccessor具体实现类,并实现类进行缓存。

  • noInflation 为 ture :返回使用字节码生成技术 MethodAccessorGenerator().generateMethod()(如ASM库)动态生成的类。(生成的类实现了 MethodAccessorImpl 接口,并包含一个 invoke 方法,该方法直接调用目标方法,而不是通过反射API。)
  • noInflation false : 代理类DelegatingMethodAccessorImpl并返回 。代理类DelegatingMethodAccessorImpl 与Native 类 NativeMethodAccessorImpl互相持有引用。

        而DelegatingMethodAccessorImpl对象 对NativeMethodAccessorImpl对象进行了代理,Method.invoke()在调用时候,实际执行的是NativeMethodAccessorImpl.invoke()方法。

       在执行NativeMethodAccessorImpl.invoke()方法时候,通过numInvocations属性对调用次数进行了计数;当调用次数超过设定次数后并且不是匿名类,则会进行新的MethodAccessorImpl的创建,通过MethodAccessorGenerator.generateMethod 使用字节码生成技术(如ASM库)动态生成一个新的类。NativeMethodAccessorImpl 对象通过自身持有的parent 属性执行parent.setDelegate(acc)操作,对DelegatingMethodAccessorImpl对象的代理对象进行切换,后续方法执行底层方式切换为新的 NativeMethodAccessor实现。

3.2.1. Method.invoke()

public Object invoke(Object obj, Object... args)throws IllegalAccessException, IllegalArgumentException,InvocationTargetException{// 判定是否绕过 Java 的访问控制检查(setAccessible(true)),允许反射代码访问私有或受保护方法或属性if (!override) {//快速的方式来进行初步的权限检查if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {Class<?> caller = Reflection.getCallerClass();//执行更详细的权限验证checkAccess(caller, clazz, obj, modifiers);}}MethodAccessor ma = methodAccessor;             if (ma == null) {// 这里会调用reflectionFactory.newMethodAccessor(this)创建一个新的MethodAccessor// 并赋值给methodAccessor,下次就不会进入到这里了// ma实际类型是DelegatingMethodAccessorImpl,代理对目标方法的调用ma = acquireMethodAccessor();}// 执行return ma.invoke(obj, args);
}
// 获取MethodAccessor实现
private MethodAccessor acquireMethodAccessor() {// 第一步:检查是否有已存在的 MethodAccessor 实例MethodAccessor tmp = null;if (root != null) tmp = root.getMethodAccessor();if (tmp != null) {methodAccessor = tmp;} else {// 第二步:如果没有已存在的 MethodAccessor 实例,通过reflectionFactory生成tmp = reflectionFactory.newMethodAccessor(this);setMethodAccessor(tmp);}return tmp;}
//缓存MethodAccessor实现
void setMethodAccessor(MethodAccessor accessor) {methodAccessor = accessor;if (root != null) {root.setMethodAccessor(accessor);}
}

       初次 执行Method.invoke 执行时,reflectionFactory.newMethodAccessor(this)创建一个新的MethodAccessor,并赋值给methodAccessor进行缓存。

3.2.2. reflectionFactory.newMethodAccessor()

public MethodAccessor newMethodAccessor(Method method) {//初始化检查checkInitted();//noInflation 用于控制反射方法访问器的生成策略,以平衡性能和资源消耗。//-通过设置系统属性 sun.reflect.noInflation,开发人员可以在特定情况下优化反射操作的性能。if (noInflation  && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {return new MethodAccessorGenerator().generateMethod(method.getDeclaringClass(),method.getName(),method.getParameterTypes(),method.getReturnType(),method.getExceptionTypes(),method.getModifiers());} else {// DelegatingMethodAccessorImpl对象代理 NativeMethodAccessorImpl对象。NativeMethodAccessorImpl acc =new NativeMethodAccessorImpl(method);DelegatingMethodAccessorImpl res =new DelegatingMethodAccessorImpl(acc);//NativeMethodAccessorImpl也持有了DelegatingMethodAccessorImpl的引用。acc.setParent(res);return res;}
}

   reflectionFactory.newMethodAccessor() 方法根据sun.reflect.noInflation 配置使用, 选择使用哪种MethodAccessor 实现。

       noInflation 为ture :返回使用字节码生成技术 MethodAccessorGenerator().generateMethod()(如ASM库)动态生成的类。(生成的类实现了 MethodAccessorImpl 接口,并包含一个 invoke 方法,该方法直接调用目标方法,而不是通过反射API。)

      noInflation 为false : 返回代理类DelegatingMethodAccessorImpl并返回 。代理类DelegatingMethodAccessorImpl 与Native 类 NativeMethodAccessorImpl互相持有引用。

3.2.3. DelegatingMethodAccessorImpl


class DelegatingMethodAccessorImpl extends MethodAccessorImpl {private MethodAccessorImpl delegate;DelegatingMethodAccessorImpl(MethodAccessorImpl delegate) {setDelegate(delegate);}public Object invoke(Object obj, Object[] args)throws IllegalArgumentException, InvocationTargetException{//标准代理模式:底层实现由持有的对象实现。return delegate.invoke(obj, args);}void setDelegate(MethodAccessorImpl delegate) {this.delegate = delegate;}
}

   DelegatingMethodAccessorImpl 持有NativeMethodAccessorImpl引用delegate,并且自身方法invoke()NativeMethodAccessorImpl.invoke()进行了包装(代理模式)。

3.2.4. NativeMethodAccessorImpl

class NativeMethodAccessorImpl extends MethodAccessorImpl {private final Method method;private DelegatingMethodAccessorImpl parent;private int numInvocations;NativeMethodAccessorImpl(Method method) {this.method = method;}public Object invoke(Object obj, Object[] args)throws IllegalArgumentException, InvocationTargetException{// numInvocations 调用次数计数//次数计数大于ReflectionFactory.inflationThreshold()并且不是匿名类切换为MethodAccessorGenerator().generateMethod();if (++numInvocations > ReflectionFactory.inflationThreshold()&& !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {MethodAccessorImpl acc = (MethodAccessorImpl)new MethodAccessorGenerator().generateMethod(method.getDeclaringClass(),method.getName(),method.getParameterTypes(),method.getReturnType(),method.getExceptionTypes(),method.getModifiers());parent.setDelegate(acc);}return invoke0(method, obj, args);}void setParent(DelegatingMethodAccessorImpl parent) {this.parent = parent;}private static native Object invoke0(Method m, Object obj, Object[] args);
}

   reflectionFactory.newMethodAccessor() 返回的是DelegatingMethodAccessorImpl 对象,并且对DelegatingMethodAccessorImpl 对象进行缓存。而DelegatingMethodAccessorImplNativeMethodAccessorImpl进行了代理,Method.invoke()在调用时候,实际执行的是NativeMethodAccessorImpl.invoke()方法。

        在执行NativeMethodAccessorImpl.invoke()方法时候,通过numInvocations属性对调用次数进行了计数;

       当调用次数超过设定次数后并且不是匿名类,则会进行新的MethodAccessorImpl的创建,通过MethodAccessorGenerator.generateMethod 使用字节码生成技术(如ASM库)动态生成一个新的类。NativeMethodAccessorImpl 对象通过自身持有的parent 属性执行parent.setDelegate(acc)操作,对DelegatingMethodAccessorImpl对象的代理对象进行切换,后续方法执行底层方式切换为新的 NativeMethodAccessor实现。

4. 用途

4.1. 动态创建和访问对象

可以在运行时动态地创建对象,而不需要在编译时知道具体的类名。

  • 示例:使用 Class.forNameConstructor.newInstance 创建对象。
Class<?> clazz = Class.forName("jvm.newInstance.NewInstanceDto");//  反射获取对象方式方式1 : 通过反射获取无参构造函数 (无参构造函数必须public修饰,否则会抛出 IllegalAccessException)
Object o1 = clazz.newInstance();
// 反射获取对象方式2 : 通过反射获取有参构造函数
Constructor<?> c1 = clazz.getDeclaredConstructor(String.class);
// 绕过 Java 的访问控制检查,允许反射代码访问私有或受保护方法或属性
c1.setAccessible(true);
Object o2 = c1.newInstance("o2-1");

4.2. 动态访问字段

可以在运行时动态地访问和修改对象的字段,即使这些字段是私有的。

  • 示例:使用 Field 类访问和修改字段。
Class<?> clazz = Class.forName("jvm.newInstance.NewInstanceDto");
Object o1 = clazz.newInstance();
// 反射方式获取属性字段
Field f1 = clazz.getDeclaredField("id");
// 绕过 Java 的访问控制检查,允许反射代码访问私有或受保护方法或属性
f1.setAccessible(true);
// 重置值:
f1.set(o1, "o1-2");

4.3. 动态调用方法

可以在运行时动态地调用对象的方法,即使这些方法是私有的。

  • 示例:使用 Method 类调用方法。
Class<?> clazz = Class.forName("jvm.newInstance.NewInstanceDto");
Object o1 = clazz.newInstance();
// 反射方式获取方法方式1
Method m1 = clazz.getDeclaredMethod("execute", String.class);
// 绕过 Java 的访问控制检查,允许反射代码访问私有或受保护方法或属性
m1.setAccessible(true);
m1.invoke(o1, "o1");

4.4. 获取类信息

可以在运行时获取类的详细信息,包括类名、父类、接口、注解等。

  • 示例:获取类的名称和父类。
Class<?> clazz = Class.forName("jvm.newInstance.NewInstanceDto");
String className = clazz.getName();
Class<?> superClass = clazz.getSuperclass();
... ... ...

4.5. 动态代理

可以在运行时创建接口的代理类,实现AOP(面向切面编程)等功能。

  • 示例:使用 Proxy 类创建动态代理。
InvocationHandler handler = new MyInvocationHandler();
NewInstanceDto proxy = (NewInstanceDto) Proxy.newProxyInstance(NewInstanceDto.class.getClassLoader(),new Class<?>[] { NewInstanceDto.class },handler
);

4.6. 注解处理

可以在运行时读取和处理类、方法、字段上的注解。

  • 示例:读取类上的注解。
Class<?> clazz =  Class.forName("jvm.newInstance.NewInstanceDto");;
MyAnnotation annotation = clazz.getAnnotation(MyAnnotation.class);

4.7. 框架和库开发

多框架和库(如Spring、Hibernate、JUnit等)广泛使用反射来实现依赖注入、ORM、单元测试等功能。

  • 示例:Spring框架使用反射实现依赖注注

4.8.插件系统

可以在运行时动态加载和卸载插件,实现模块化和可扩展的系统架构。

  • 示例:动态加载插件。
File pluginDir = new File("plugins");
File[] pluginFiles = pluginDir.listFiles((dir, name) -> name.endsWith(".jar"));for (File pluginFile : pluginFiles) {URL url = pluginFile.toURI().toURL();URLClassLoader classLoader = new URLClassLoader(new URL[] { url });Class<?> class = Class.forName("jvm.newInstance.NewInstance", true, classLoader);Object plugin =  class.getDeclaredConstructor().newInstance()
}

5. 示例

 public static void main(String[] args) throws Exception {// 获取class对象Class<?> clazz = Class.forName("jvm.newInstance.NewInstanceDto");//  反射获取对象方式方式1 : 通过反射获取无参构造函数 (无参构造函数必须public修饰,否则会抛出 IllegalAccessException)Object o1 = clazz.newInstance();// 反射获取对象方式2 : 通过反射获取有参构造函数Constructor<?> c1 = clazz.getDeclaredConstructor(String.class);// 绕过 Java 的访问控制检查,允许反射代码访问私有或受保护方法或属性c1.setAccessible(true);Object o2 = c1.newInstance("o2-1");// 反射方式获取方法方式1Method m1 = clazz.getDeclaredMethod("execute", String.class);// 绕过 Java 的访问控制检查,允许反射代码访问私有或受保护方法或属性m1.setAccessible(true);// 反射获取方法方式2:Method m2 = clazz.getDeclaredMethod("execute", String.class, int.class);// 绕过 Java 的访问控制检查,允许反射代码访问私有或受保护方法或属性m2.setAccessible(true);// 反射方式获取属性字段Field f1 = clazz.getDeclaredField("id");// 绕过 Java 的访问控制检查,允许反射代码访问私有或受保护方法或属性f1.setAccessible(true);// 调用方法结果:>>> >>> >>> execute info o1 this.id :  nullm1.invoke(o1, "o1");// 重置值:id -> o1-2f1.set(o1, "o1-2");// 调用方法结果:>>> >>> >>> execute info o1 this.id :  o1-2m1.invoke(o1, "o1");// 调用方法结果:>>> >>> >>> execute  info 02 this.id :  o2-1 key : 1m2.invoke(o2, "02", 1);// 重置值:id -> o2-2f1.set(o2, "o2-2");// 调用方法结果:>>> >>> >>> execute  info 02 this.id :  o2-1 key : 2m2.invoke(o2, "02", 2);}


http://www.mrgr.cn/news/68923.html

相关文章:

  • java基础day15 ----多线程
  • Scala的Map集合(不可变)
  • 温度传感器的工作原理
  • Trimble X12三维激光扫描仪正在改变游戏规则【上海沪敖3D】
  • 链式结构二叉树
  • 学习日记_20241110_聚类方法(K-Means)
  • TCP(传输控制协议)和UDP(用户数据报协议)
  • 智能制造基础- TPM(全面生产维护)
  • Python酷库之旅-第三方库Pandas(203)
  • STL---迭代器
  • 出现 SLF4J: Class path contains multiple SLF4J bindings 原理分析
  • Java开发插件:JRebel热部署(最佳实践+激活方式)
  • 自动化测试工具Ranorex Studio(二十六)-对象库设置对话框
  • Spring框架之策略模式 (Strategy Pattern)
  • 二项堆 (Binomial Heap)、Fibonacci 堆详细解读
  • [数组排序] 0506. 相对名次
  • XML 现实案例:深入解析与应用
  • Java 归并排序算法详解
  • 【C语言】浮点型数据存储 和 整型数据存储的区别
  • QT最新版6.8在线社区版安装教程
  • C语言 | Leetcode C语言题解之第552题学生出勤记录II
  • PyQt入门指南四十七 内存管理技巧
  • 解释Python中的装饰器的作用
  • SpringBoot12-Shiro
  • 论文重复率从58%降到38%,死活降不下去了,怎么办?
  • 【C语言】位运算