首页 课程 师资 教程 报名

Javaweb学习视频:反射动态代理

  • 2020-03-12 09:19:07
  • 2166次 动力节点


  一、类加载


  定义


  当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化


  加载


  就是指将.class文件读入内存,并为之创建一个Class对象。任何类被使用时系统都会建立一个Class对象。


  连接


  验证是否有正确的内部结构,并和其他类协调一致


  准备负责为类的静态成员分配内存,并设置默认初始化值


  解析将类的二进制数据中的符号引用替换为直接引用


  初始化就是我们以前讲过的初始化步骤


  2.加载的时机


  创建类的实例


  访问类的静态变量,或者为静态变量赋值


  调用类的静态方法


  使用反射方式来强制创建某个类或接口对应的java.lang.Class对象


  加载某个类的子类


  直接使用java.exe命令来运行某个主类


  真正在使用这个类型的时候


  二、类加载器的概述和分类


  定义


  负责将.class文件加载到内存中,并为之生成对应的Class对象。虽然我们不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行


  2.类加载器的分类


  BootstrapClassLoader根类加载器


  ExtensionClassLoader扩展类加载器


  SysetmClassLoader系统类加载器


  AppClassLoader应用类加载器


  3.类加载器的作用


  BootstrapClassLoader根类加载器


  也被称为引导类加载器,负责Java核心类的加载


  比如System,String等。在JDK中JRE的lib目录下rt.jar文件中


  ExtensionClassLoader扩展类加载器


  负责JRE的扩展目录中jar包的加载。


  在JDK中JRE的lib目录下ext目录


  SysetmClassLoader系统类加载器


  负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径


  AppClassLoader加载其他类


  负载一些非核心类和程序猿自己写的类


  4.演示

  publicstaticvoidmain(String[]args){

  //获取TestDemo类的类加载器

  System.out.println(TestDemo.class.getClassLoader());

  }


  三、自定义类加载器


  双亲委派模型


  当前类加载器从自己已经加载的类中查询是否此类已经加载,如果已经加载则直接返回原来已经加载的类。


  如果没有找到,就去委托父类加载器去加载(如代码c=parent.loadClass(name,false)所示)。父类加载器也会采用同样的策略,查看自己已经加载过的类中是否包含这个类,有就返回,没有就委托父类的父类去加载,一直到根类加载器。因为如果父加载器为空了,就代表使用根类类加载器作为父加载器去加载


  如果根类类加载器加载失败(例如在$JAVA_HOME/jre/lib里未查找到该class),会使用拓展类加载器来尝试加载,继续失败则会使用AppClassLoader来加载,继续失败则会抛出一个异常ClassNotFoundException,然后再调用当前加载器的findClass()方法进行加载


  2.好处


  主要是为了安全性,避免用户自己编写的类动态替换Java的一些核心类,比如String。


  同时也避免了类的重复加载,因为JVM中区分不同类,不仅仅是根据类名,相同的class文件被不同的ClassLoader加载就是不同的两个类


  案例演示

  publicclassMyClassLoaderextendsClassLoader{

  privateStringpath;

  publicMyClassLoader(Stringpath){

  super();

  this.path=path;

  }

  @Override

  protectedClass<?>findClass(Stringname)throwsClassNotFoundException{

  //读取本地文件

  byte[]bs=getBytes(path);

  //将字节数组装载成Class对象

  Class<?>clazz=this.defineClass(name,bs,0,bs.length);

  returnclazz;

  }

  privatebyte[]getBytes(Stringpath){

  try(

  FileInputStreamfis=newFileInputStream(path);

  ByteArrayOutputStreambos=newByteArrayOutputStream();

  ){

  byte[]bs=newbyte[1024];

  intlen;

  while((len=fis.read(bs))!=-1){

  bos.write(bs,0,len);

  }

  returnbos.toByteArray();

  }catch(Exceptione){

  }

  returnnull;

  }

  }

  publicstaticvoidmain(String[]args)throwsException{

  MyClassLoaderclassLoader=newMyClassLoader("D:\Student.class");

  Class<?>clazz=classLoader.findClass("com.qianfeng.Student");

  //Class<?>class1=Class.forName("com.qianfeng.Student",true,classLoader);

  Objectobj=clazz.newInstance();

  System.out.println(obj.getClass().getClassLoader());

  }


  四、反射


  定义


  JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法


  对于任意一个对象,都能够调用它的任意一个方法和属性


  这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制


  要想解剖一个类,必须先要获取到该类的字节码文件对象


  而解剖使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象


  说白了就是获取一个类的骨架


  2.获取字节码的三种方式


  对象.getClass()


  类名.class


  Class类中静态方法forName("类名")


  3.演示

  publicstaticvoidmain(String[]args)throwsException{

  Studentstudent=newStudent();

  Class<?>clazz1=student.getClass();

  Class<?>clazz2=Student.class;

  Class<?>clazz3=Class.forName("com.qianfeng.Student");

  }


  五、反射获取构造函数


  定义


  Class类的newInstance()方法是使用该类无参的构造函数创建对象


  如果一个类没有无参的构造函数,就不能这样创建了,可以调用Class类的getConstructor(String.class,int.class)方法获取一个指定的构造函数然后再调用Constructor类的newInstance("张三",20)方法创建对象


  2.演示

  publicstaticvoidmain(String[]args)throwsException{

  Class<?>clazz=Class.forName("com.qianfeng.Student");

  Studentobject=(Student)clazz.newInstance();

  object.method();

  }


Javaweb学习视频:反射动态代理


    以上就是动力节点Java培训机构小编介绍的“Javaweb学习视频:反射动态代理”的内容,希望对大家有帮助,如有疑问,请在线咨询,有专业老师随时为你服务。


选你想看

你适合学Java吗?4大专业测评方法

代码逻辑 吸收能力 技术学习能力 综合素质

先测评确定适合在学习

在线申请免费测试名额
价值1998元实验班免费学
姓名
手机
提交