返回

深入理解ClassLoader加载Resource源码

后端

前言

在Java开发中,经常会遇到资源加载的需求,例如加载配置文件、图片、声音等。这些资源通常存储在文件系统、数据库或网络上。为了方便开发人员访问这些资源,Java提供了ClassLoader类。ClassLoader负责加载和管理Java应用程序所需的类、资源和其他代码。

ClassLoader加载Resource的原理

ClassLoader加载Resource的过程大致如下:

  1. 首先,ClassLoader会尝试从当前类的类路径中加载Resource。类路径是一个由目录和JAR文件组成的集合,这些目录和JAR文件包含了类的二进制代码。
  2. 如果ClassLoader在类路径中找不到Resource,它会尝试从父ClassLoader加载Resource。父ClassLoader通常是应用程序的主类加载器,它负责加载应用程序的类和资源。
  3. 如果父ClassLoader也找不到Resource,ClassLoader会尝试从应用程序的扩展类加载器加载Resource。应用程序的扩展类加载器负责加载应用程序的扩展类和资源。
  4. 如果应用程序的扩展类加载器也找不到Resource,ClassLoader会尝试从应用程序的系统类加载器加载Resource。应用程序的系统类加载器负责加载Java虚拟机的类和资源。

ClassLoader加载Resource的源码分析

为了更好地理解ClassLoader加载Resource的原理,我们来看一下ClassLoader加载Resource的源码。ClassLoader加载Resource的源码位于java.lang.ClassLoader类中。

public URL getResource(String name) {
    URL url = findResource(name);
    if (url == null) {
        url = findResource(name, true);
    }
    return url;
}

从这段代码可以看出,ClassLoader加载Resource时,首先会调用findResource方法查找Resource。findResource方法的源码如下:

public URL findResource(String name) {
    return findResource(name, false);
}

从这段代码可以看出,findResource方法有两个重载方法,一个不带参数,另一个带一个布尔参数。不带参数的findResource方法调用带参数的findResource方法,并传入false作为参数。

public URL findResource(String name, boolean checkParent) {
    URL url = null;
    if (name == null) {
        throw new NullPointerException("name cannot be null");
    }
    synchronized (resources) {
        url = resources.get(name);
        if (url != null) {
            return url;
        }
        if (checkParent) {
            url = parent.findResource(name);
        }
    }
    return url;
}

从这段代码可以看出,带参数的findResource方法首先会检查Resource是否已经加载过。如果Resource已经加载过,则直接返回Resource的URL。如果Resource没有加载过,则会检查父ClassLoader是否加载过该Resource。如果父ClassLoader加载过该Resource,则直接返回Resource的URL。

如果父ClassLoader也没有加载过该Resource,则ClassLoader会尝试从自己的类路径中加载Resource。ClassLoader的类路径是一个由目录和JAR文件组成的集合,这些目录和JAR文件包含了类的二进制代码。

如果ClassLoader从自己的类路径中找到了Resource,则会将Resource的URL缓存起来,并返回Resource的URL。如果ClassLoader从自己的类路径中找不到Resource,则会返回null。

总结

通过对ClassLoader加载Resource的源码分析,我们了解了ClassLoader加载Resource的原理。ClassLoader加载Resource时,首先会尝试从当前类的类路径中加载Resource。如果找不到Resource,则会尝试从父ClassLoader加载Resource。以此类推,最终会尝试从应用程序的系统类加载器加载Resource。