java反射和动态代理基础

类加载

  • 类加载指的是将类的class文件读入内存,并为之创建一个java.lang.Class对象
  • 当一个变量被修饰成static final,并在编译器就能确定其值,也就是常量,那么通过类名.变量名访问该变量时不会加载该类(也就是访问常量并不会初始化这个类)

类初始化时机

类从加载到虚拟机内存开始,到卸载出内存为止,真个生命周期包括:加载(Loading),验证(Verification),准备(Preparation),解析(Resolution),初始化(Initialization),使用(Using)和卸载(Unloading)七个阶段。其中,验证、准备、解析三个部分统称为连接(Linking)

 

1. new对象、调用类的静态方法或者静态变量时
2. 虚拟机启动时,加载用户指定的main方法的所在类
3. 通过反射调用某个类
4. 初始化一个类时先初始化它的父类
5. 初始化某个类的子类

中心思想:初始化时机为该类首次主动使用
以下情况不会初始化

1、通过子类类名调用父类静态代码,不会触发子类的初始化。
2、通过数组来创建对象不会触发此类的初始化。
3、通过调用静态常量不会触发初始化。

类加载器

1. Bootstrap ClassLoader,被称为引导(也称为原始或根)类加载器。它负责加载 Java的核心类。在Sun的JVM中,当执行java.exe的命令时使用-Xbootclasspath选项或使用-D选项指定sun.boot.class.path系统属性值可以指定加载附加的类。根类加载器非常特殊,它并不是java.lang.ClassLoader的子类,而是由JVM自身实现的。
2. Extension ClassLoader,被称为扩展类加载器,它负责加载JRE的扩展目录(JAVA_HOME/jre/lib/ext或由java.ext.dirs系统属性指定的目录)中的JAR的类包。
3. System ClassLoaser,被称为系统(也称为应用)类加载器,它负责在JVM启动时,加载来自命令java中的-classpath选项或java.class.path系统属性,或CLASSPATH环境变量所指定的JAR包和类路径。

反射

概念

官方解释:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

简单理解:反射就是直接通过字节码文件class,去使用它的变量,方法,和构造

使用步骤

  1. 获得class对象
  2. 从class中获取信息

获取class对象

共有三种方式:

  1. 使用Class类的forName(类的全名),该方法需要传入参数,参数为某个类的全名(包名+类名)

Class.forName("com.test.User");

  1. 调用某个类的class属性获取其对应的Class对象

User.class;

  1. 调用某个对象的getClass()方法

User.getClass();

从Class中获取信息

获取对应类中的构造器,类型为Constructor
  1. 获得所有public修饰的构造方法

public Constructor[] getConstructors();

  1. 获得所有构造方法,包括私有

public Constructor[] getDeclaredConstructors();

  1. 获取指定的public修饰构造方法,参数是该构造方法里参数的类型的class对象

public Constructor getConstructor(Class<?>... parameterTypes);

例如:

enter description here

 
  1. 获取指定构造方法,包括私有

public Constructor getDeclaredConstructor(Class<?>... parameterTypes);

使用:拿到构造方法后,用Constructor对象调用newInstance()方法就可以调用该构造方法创建对象。例如

enter description here

 

获得私有构造方法也可以使用,在newInstance操作前设置一下构造方法的访问权限:

constructor.setAccessible(true);

获取方法,类型为Method

  1. 获取指定的public方法

public Method getMethod(String methodName ,Class<?>… parameterTypes) //第一个参数为方法名,后面参数为形参的类型的class
2. 获取所有public方法

public Method[] getMethods()
3. 获取指定的方法,包括私有

public Method getDeclaredMethods(String name ,Class<?>… parameterTypes)
4. 获取所有方法,包括私有

public Method[] getDeclaredMethods()

使用:invoke(对象名,实参)

enter description here

 

获取变量,类型为Field

  1. 获取指定的public变量

public Field getField(String name)

  1. 获取所有public变量

public Field[] getFields()

  1. 获取指定的变量,包括私有

public getDeclaredField(String name)

  1. 获取所有变量,包括私有

public Field[] getDeclaredFields()

使用:set(对象,值):设置属性;get(对象):获取属性值

enter description here

 

结合配置文件的使用

enter description here

 

操作数组

可以通过java.lang.reflect下的Array类来操作数组

  • static Object new Instance(Class<?> componentType,int... length):创建一个具有指定的元素类型、指定维度的数组
  • static xxx get(Object array,int index)
  • static void set(Object array,in index,xxx value)
enter description here

 

动态代理

  • 通过Proxy创建动态代理对象

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) //三个参数分别为目标对象的类加载器,目标对象所有接口,实现了InvocationHandler接口的类

  • InvocationHandler接口,重写invoke方法
enter description here

 
enter description here

 

作用:
1. 解决多个方法中调用了一个通用功能的问题
2. 解耦

举例说明
在开发过程中,有些功能代码是可以共用的。比如有个学生类,里面有个写作业方法,写作业包含三个步骤,打开作业本,写,合上;老师类里有个批作业方法,包含三个步骤:打开作业本,批改,合上;学生类里还有个抄作业方法,包含三个步骤:打开作业本,抄作业,合上(什么鬼啊,我么都是好学生,抄什么作业啊)。
好的不要在意细节,以上例子只是想来说明一下代理的作用。对于以上的三个方法,打开和合上作业本就属于相同的代码块,于是初学者开发时为了节省时间会选择直接复制粘贴,像下面这样。

enter description here

 

有一天,你发现需要修改红色部分的代码块,而你之前将此部分的代码块复制了好多遍,这时你发现,哇,维护起来好不方便哦。于是你想到了封装,可以把红色部分代码封装起来,在其他代码块里直接调用啊。


 

此时虽然解决了代码复用问题,但是却又提高了代码之间的耦合性。(开发的标准是要尽量做到高内聚,低耦合)现在的代码是这个样子:

enter description here

 

而且调用方法的这句话也是一直在重复出现很麻烦哎
现在就让我们用动态代理来改进,所有的代理,就是帮你去做事啊,我们只需要写自己的专有方法即可,执行相同部分的代码这一步操作可以交给代理来做。
第一步,创建Student接口,包含写作业抄作业两个基本方法(jdk提供的动态代理只能做接口代理,所有要定义接口)
enter description here

 

第二步,编写学生接口的实现类StudentImpl
enter description here

 

第三步,实现InvocationHandler接口
enter description here

 

第四步,编写代理工厂
enter description here

 

第五步,测试
enter description here

 

调用代理对象的方法时,其实走的就是重写的invoke方法,invoke方法里我们去调用了共用的方法,调用对象本身方法时就用到了反射
原文地址:https://www.cnblogs.com/duibd/p/12060964.html