参考 https://www.cnblogs.com/whgk/p/6122036.html
https://blog.csdn.net/huangliniqng/article/details/88554510
https://www.jianshu.com/p/9bcac608c714
https://cloud.tencent.com/developer/article/1461796
https://www.liaoxuefeng.com/wiki/1252599548343744/1264804593397984
反射和动态代理是非常重要的基础概念,可以说,诸多框架的实现都依赖了这两种手段,这篇博客,博主会来学习总结一下反射和动态代理的相关知识,写博客也是为了知识储备,可以不记得细节,但是用到了,要记得这么个东西,要知道怎么查找材料
jvm虚拟机在创建对象的时候,会先把这个类对应的class文件加载到方法区中,然后在堆上创建class对象(字节码对象),并由此字节码对象来创建具体的对象。所以,字节码对象中会包含对应类内部的属性、构造和方法等,通过反射技术,我们可以直接获取这些属性,调用该类的方法(包括私有属性和私有方法)。
一 、什么是反射?
在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制。通俗点讲,通过反射,该类对我们来说是完全透明的,想要获取任何东西都可以。
所以根据之前的介绍,既然class对象中包含我们想要的东西,那么反射自然是依赖于class对象的
获取一个类对应class对象的方式有三种:
1、Class clazz1 = Class.forName("全限定类名"); //通过Class类中的静态方法forName,直接获取到一个类的字节码文件对象,此时该类还是源文件阶段,并没有变为字节码文件。
2、Class clazz2 = Person.class; //当类被加载成.class文件时,此时Person类变成了.class,在获取该字节码文件对象,也就是获取自己, 该类处于字节码阶段。
3、Class clazz3 = p.getClass(); //通过类的实例获取该类的字节码文件对象,该类处于创建对象阶段
有了字节码文件对象才能获得类中所有的信息,我们在使用反射获取信息时,也要考虑使用上面哪种方式获取字节码对象合理,视不同情况而定。下面介绍Class类的功能。
对class对象的常见操作API如下
二、反射机制能够获取哪些信息?Class类的API详解。
2.1、通过字节码对象创建实例对象
2.2、获取指定构造器方法。constructor 如果没有无参构造,只有有参构造如何创建实例呢?看下面
总结上面创建实例对象:Class类的newInstance()方法是使用该类无参的构造函数创建对象, 如果一个类没有无参的构造函数, 就不能这样创建了,可以调用Class类的getConstructor(String.class,int.class)方法获取一个指定的构造函数然后再调用Constructor类的newInstance("张三",20)方法创建对象
获取全部构造方法
2.3、获取成员变量并使用 Field对象
获取指定成员变量
Class.getField(String)方法可以获取类中的指定字段(可见的), 如果是私有的可以用getDeclaedField("name")方法获取,通过set(obj, "李四")方法可以设置指定对象上该字段的值, 如果是私有的需要先调用setAccessible(true)设置访问权限,用获取的指定的字段调用get(obj)可以获取指定对象中该字段的值
获取全部成员变量
2.4、获得方法并使用 Method
Class.getMethod(String, Class...) 和 Class.getDeclaredMethod(String, Class...)方法可以获取类中的指定方法,如果为私有方法,则需要打开一个权限。setAccessible(true);
用invoke(Object, Object...)可以调用该方法,
跟上面同理,也能一次性获得所有的方法
2.5、获得该类的所有接口
Class[] getInterfaces():确定此对象所表示的类或接口实现的接口
返回值:接口的字节码文件对象的数组
2.6、获取指定资源的输入流
InputStream getResourceAsStream(String name)
return:一个 InputStream 对象;如果找不到带有该名称的资源,则返回 null
参数:所需资源的名称,如果以"/"开始,则绝对资源名为"/"后面的一部分。
动态代理
代理模式,即代理对象代替被代理对象执行任务,
一种设计模式,常见的设计模式共23种,会有专门的博客去介绍,这里不细说
提到动态代理,也提一下静态代理,“动”与“静”的区别,就是是否运行时
动态代理在运行时执行被代理对象的任务,而静态代理是写死的。
这里大致解释一下动态代理的价值所在,我们普通调用执行的方式为new Student()对象,然后对象调用方法,弹有了动态代理,我们可以不必自己创建对象调用方法,而是换作代理对象来代替原对象执行,那么我们就可以对任务的执行进行干预,比如,方法执行前我们添加一个事务操作,并且根据方法的执行状态我们可以判断是否要回滚事务。日志记录的也是运行时状态,还有耳熟能详的spring面向切面编程AOP。
- 日志集中打印
- 事务
- 权限管理
- AOP