WebAppClassLoader(Tomcat)和 LaunchedURLClassLoader(Spring Boot)类加载器详解

发布于:2025-09-04 ⋅ 阅读:(22) ⋅ 点赞:(0)

它们都不是完全抛弃双亲委派机制,而是在特定场景下“打破”或“绕过”了部分双亲委派流程,以满足各自的运行需求。


🔍 先回顾:双亲委派机制

  • 标准流程:类加载请求先委托给父加载器,父加载器找不到才由自己加载
  • 好处:安全(防止核心类被篡改)、避免重复加载、类隔离

🛠 WebAppClassLoader(Tomcat)

  • 用途:隔离不同 Web 应用的类,支持热部署
  • 破坏点
    • Tomcat 的 WebAppClassLoader 在加载类时,会先尝试自己加载(尤其是 WEB-INF/classesWEB-INF/lib 下的类),再委托父加载器
    • 这样可以让 Web 应用自己的类覆盖容器或 JDK 提供的同名类(除了一些受保护的包)
  • 原因
    • 支持应用自带依赖版本
    • 实现应用之间的类隔离
    • 支持热部署(重新加载类)

🛠 LaunchedURLClassLoader(Spring Boot)

  • 用途:支持 Spring Boot 可执行 JAR(fat jar)结构,从 BOOT-INF/classesBOOT-INF/lib 中加载类
  • 破坏点
    • 它继承自 URLClassLoader,但加载逻辑会优先从自身的 URL 列表(fat jar 内部路径)找类,而不是严格先委托父加载器
    • 这样可以让应用打包在 JAR 内的类优先于外部类加载
  • 原因
    • 让 Spring Boot 内嵌依赖优先加载
    • 保证 fat jar 内部的类路径结构可直接运行
    • 避免依赖冲突

📌 总结对比

类加载器 是否完全跳过双亲委派 破坏方式 目的
WebAppClassLoader ❌(部分破坏) 部分包优先自己加载 应用隔离、热部署
LaunchedURLClassLoader ❌(部分破坏) 优先加载 fat jar 内部类 支持可执行 JAR、自带依赖优先

💡 一句话总结
它们都保留了双亲委派的大框架,但在类查找顺序上做了“反转”或“短路”,以满足类隔离、热部署、可执行 JAR等特殊需求。



🎨 类加载流程对比图

🟦 标准双亲委派机制(父优先)
[请求加载类] 
   ⬇️ 委托父加载器
      ⬇️ 父找到 → ✅ 返回类
      ⬇️ 父找不到 → 自己加载

🟩 WebAppClassLoader(Tomcat,子优先)
[请求加载类]
   ⬇️ 先检查自己(WEB-INF/classes, WEB-INF/lib)
      ⬇️ 找到 → ✅ 返回类
      ⬇️ 找不到 → 委托父加载器
   (部分包仍父优先,保护核心类)

🟨 LaunchedURLClassLoader(Spring Boot,子优先)
[请求加载类]
   ⬇️ 先检查自己(BOOT-INF/classes, BOOT-INF/lib)
      ⬇️ 找到 → ✅ 返回类
      ⬇️ 找不到 → 委托父加载器
   (支持 Fat JAR 结构,内嵌依赖优先)

🔍 关键差异

  • 标准双亲委派:父优先,安全性高,避免重复加载
  • WebAppClassLoader:对子类路径(WEB-INF/classesWEB-INF/lib)优先加载,实现应用隔离和热部署
  • LaunchedURLClassLoader:对子类路径(BOOT-INF/classesBOOT-INF/lib)优先加载,支持 Spring Boot 可执行 JAR


网站公告

今日签到

点亮在社区的每一天
去签到