zoukankan      html  css  js  c++  java
  • Java 之 类加载器对象—ClassLoader

    一、获取 ClassLoader 对象

      获取某个类的类加载对象需要两步:

      ① 获取某个类的 Class  对象;

      ② 通过 Class 对象调用 getClassLoader() 方法获取类加载器对象

    二、java.lang.ClassLoader 对象

      ClassLoader 类是一个抽象类,学习一下 ClassLoader 的相关方法:

    public final ClassLoader getParent():返回委托的父类加载器。一些实现可能使用 null 来表示引导类加载器;
    public static ClassLoader getSystemClassLoader():返回委托的系统类加载器;
    public Class<?> loadClass(String name):使用指定的二进制名称(类的全限定名)来加载类。
        例如:java.lang.String,注意内部类的名称:匿名内部类(外部类的全限定名$编号)、局部内部类(外部类的全限定名$编号+类名)、成员/静态内部类(外部类的全限定名$+类名); protected Class<?> findClass(String name):使用指定的二进制名称(类的全限定名)来查找类。此方法应该被类加载器的实现重写,该实现按照委托模型来加载类。
                              在通过父类加载器检查所请求的类后,此方法将被 loadClass 方法调用; protected final Class<?> findLoadedClass(String name):返回Class 对象,如果类没有被加载,则返回 null; protected final Class<?> defineClass(String name,byte[] b,int off,int len):将一个 byte 数组转换为 Class 类的实例;

      

       Demo:自定义类加载器示例

     1 import java.io.ByteArrayOutputStream;
     2 import java.io.File;
     3 import java.io.FileInputStream;
     4 import java.io.FileNotFoundException;
     5 import java.io.IOException;
     6 import java.io.InputStream;
     7 
     8 public class FileClassLoader extends ClassLoader{
     9     private String rootDir;//指定加载路径
    10     
    11     public FileClassLoader(String rootDir){
    12         this.rootDir = rootDir;
    13     }
    14     
    15     @Override
    16     protected Class<?> findClass(String name) throws ClassNotFoundException {
    17         //首先检查请求的类型是否已经被这个类装载器装载到命名空间中了,如果已经被装载,直接返回;
    18         Class<?> c = findLoadedClass(name);
    19         
    20         if(c ==null){
    21             //委派类加载器请求给父类加载器,如果父类加载器能够完成,则返回父类加载器加载的Class实例;
    22             ClassLoader parent = this.getParent();
    23             try {
    24                 c = parent.loadClass(name);
    25                 //加异常处理,父类加载不到,然后自己加载
    26             } catch (Exception e) {
    27             }
    28             
    29             //调用本类加载器的findClass()方法,试图获取对应的字节码,如果获取的到,则调用defineClass()导入类型到方法区;
    30             //如果获取不到对应的字节码或其他原因失败,则异常,终止加载过程
    31             if(c == null){
    32                 byte[] classData = getClassData(name);
    33                 if(classData == null){
    34                     throw new ClassNotFoundException();
    35                 }else{
    36                     c = defineClass(name, classData, 0, classData.length);
    37                 }
    38             }
    39         }
    40         return c;
    41     }
    42     
    43     //把.class文件的内容读取到一个字节数组中
    44     //为什么要读取的字节数组中,因为protected final Class<?> defineClass(String name,byte[] b,int off,int len)
    45     private byte[] getClassData(String name) {
    46         String path = rootDir + File.separator + name.replace(".", File.separator)+".class";
    47         InputStream is = null;
    48         ByteArrayOutputStream baos = null;
    49         try {
    50             is = new FileInputStream(path);
    51             baos =new ByteArrayOutputStream(); 
    52             byte[] buffer = new byte[1024];
    53             int len;
    54             while((len = is.read(buffer))!=-1){
    55                 baos.write(buffer, 0, len);
    56             }
    57             return baos.toByteArray();
    58         } catch (FileNotFoundException e) {
    59             e.printStackTrace();
    60         } catch (IOException e) {
    61             e.printStackTrace();
    62         }finally{
    63             try {
    64                 if(is!=null){
    65                     is.close();
    66                 }
    67             } catch (IOException e) {
    68                 e.printStackTrace();
    69             }
    70         }
    71         return null;
    72     }
    73 }
    74 
    75 public class TestFileClassLoader {
    76 
    77     public static void main(String[] args) throws ClassNotFoundException {
    78         FileClassLoader fsc = new FileClassLoader("D:/java/code");
    79         Class<?> uc = fsc.loadClass("com.ks.UserManager");
    80         System.out.println(uc);
    81         
    82         Class<?> sc = fsc.loadClass("java.lang.String");
    83         System.out.println(sc);
    84         System.out.println(sc.getClassLoader());//null,因为委托给父类加载器...一直到引导类加载器
    85     }
    86 
    87 }

    三、类加载器加载资源文件

      ClassLoader 类的职责就是根据一个指定的类的名称,找到或者生成其对应的字节代码,然后从这些字节代码中定义出一个 Java类,即 java.lang.Class 类的一个实例。除此之外,ClassLoader 还负责加载 Java 应用所需的资源,如图像文件和配置文件等。

      案例一:加载类路径(如:src 下)jdbc.properties 资源文件

          扩展:SourceFolder:源代码文件夹,一般会单独用一个config这种SourceFolder来装配置文件、等价于src,不同于普通的 Folder

            代码示例:

     1 username=root
     2 password=123456
     3 url=jdbc:mysql://localhost:3306/test
     4 
     5 package com.atguigu.loader;
     6 
     7 import java.io.IOException;
     8 import java.util.Properties;
     9 
    10 public class TestLoaderProperties {
    11     public static void main(String[] args) {
    12         Properties pro = new Properties();
    13         try {
    14             pro.load(ClassLoader.getSystemResourceAsStream("jdbc.properties"));
    15             System.out.println(pro);
    16         } catch (IOException e) {
    17             e.printStackTrace();
    18         }
    19                 System.out.println(pro);
    20         System.out.println(pro.getProperty("username"));
    21     }
    22 }
    23         

      案例二:获取存放在“com.ks.reflect” 包下面的 demo.properties 文件

          代码示例:

     1   @Test
     2     public void test() throws IOException{
     3         Properties pro = new Properties();//集合,map,key=value
     4         
     5         Class clazz = Test.class;   //获取本类的 Class 对象
     6         ClassLoader loader = clazz.getClassLoader();  //获取类加载器
     7         InputStream in = loader.getResourceAsStream("com/ks/reflect/demo.properties");
     8         
     9         pro.load(in);
    10         
    11         System.out.println(pro);
    12         System.out.println(pro.getProperty("name"));
    13     }

      案例三:获取当前项目下的 out.properties 文件,不在 src 下面(这个文件没有在编译目录下,不需要使用类加载器)

          代码示例:

     1    @Test
     2     public void test() throws IOException{
     3         Properties pro = new Properties(); 4         
     5         //在项目的根路径下,不在src里面
     6         pro.load(new FileInputStream("out.properties"));
     7         
     8         System.out.println(pro);
     9         System.out.println(pro.getProperty("out"));
    10     }
  • 相关阅读:
    Python3字典中items()和python2.x中iteritems()有什么区别
    python中使用zip函数出现<zip object at 0x02A9E418>
    python中字符串连接的四种方式
    Python如何规定对方输入的数字必须是整数?
    C# 自定义控件VS用户控件
    c#使用Split分割换行符
    C# 读取app.config配置文件 节点键值,提示 "配置系统未能初始化" 错误的解决方案
    安装MySql for Visual Studio的坑
    MySql Access denied for user 'root'@'localhost' (using password:YES) 解决方案
    VS2010 VS2012 VS2013 VS2015启动调试时老是提示正在下载公共符号
  • 原文地址:https://www.cnblogs.com/niujifei/p/12311385.html
Copyright © 2011-2022 走看看