返回

让你秒懂SpringBoot的FatJar加载原理

后端

SpringBoot加载FatJar:深入剖析自定义类加载器

理解FatJar

FatJar是一种Java可执行JAR文件,它包含了整个应用程序,包括依赖项和资源。它允许应用程序在不部署外部依赖项的情况下独立运行。

SpringBoot加载FatJar的原理

1. 自定义类加载器

SpringBoot使用自定义的类加载器FatJarClassLoader加载FatJar。FatJarClassLoader扩展了URLClassLoader,并覆盖了findClass()方法。在这个方法中,FatJarClassLoader首先尝试从FatJar中加载类,如果加载失败,再从父类加载器中加载。

2. 加载FatJar

SpringBoot通过调用FatJarClassLoaderloadJar()方法加载FatJar。loadJar()方法将FatJar中的所有类加载到内存中。

3. 读取嵌套JAR中的类

FatJar可能包含嵌套的JAR文件,SpringBoot可以使用FatJarClassLoadergetResource()方法读取这些类。getResource()方法返回一个URL对象,SpringBoot可以使用它来加载嵌套JAR中的类。

FatJar如何读取嵌套JAR中的类

FatJarClassLoader使用自定义的类加载器FatJarChildClassLoader从嵌套JAR中加载类。FatJarChildClassLoader也扩展了URLClassLoader,并覆盖了findClass()方法。在这个方法中,FatJarChildClassLoader首先尝试从嵌套JAR中加载类,如果加载失败,再从父类加载器中加载。

总结

SpringBoot通过自定义类加载器FatJarClassLoaderFatJarChildClassLoader加载FatJar并读取嵌套JAR中的类。这些类加载器使用FatJar的MANIFEST.MF文件来确定哪些类存在于FatJar和嵌套JAR中。

代码示例

// 自定义类加载器
public class FatJarClassLoader extends URLClassLoader {

    public FatJarClassLoader(URL[] urls) {
        super(urls);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {
            // 尝试从FatJar中加载类
            return findClass(name);
        } catch (ClassNotFoundException e) {
            // 从父类加载器加载类
            return super.findClass(name);
        }
    }
}
// 加载FatJar
FatJarClassLoader classLoader = new FatJarClassLoader(fatJarUrl);
classLoader.loadJar();
// 读取嵌套JAR中的类
URL resourceUrl = classLoader.getResource("nested.jar");
Class<?> nestedClass = classLoader.loadClass(resourceUrl.toString());

常见问题解答

1. 为什么使用FatJar?

FatJar可以简化部署,因为应用程序及其依赖项都包含在一个可执行文件中。

2. FatJarClassLoaderFatJarChildClassLoader有什么区别?

FatJarClassLoader加载FatJar,而FatJarChildClassLoader加载嵌套JAR。

3. MANIFEST.MF文件是如何工作的?

MANIFEST.MF文件是JAR文件的一部分,它包含有关JAR中类的信息。

4. 如果类在FatJar和嵌套JAR中都存在,会发生什么?

类加载器将优先从FatJar加载类。

5. 这种方法是否有任何缺点?

这种方法可能会导致启动时间稍长,因为类加载器需要扫描FatJar和嵌套JAR中的所有类。