springboot的双亲委派

双亲委派模型(Parent Delegation Model)是 Java 类加载机制中的一种设计模式,用于确保 Java 类加载的一致性和安全性。这个模型规定,当一个类加载器加载一个类时,它首先将加载请求委派给父类加载器处理,只有当父类加载器无法完成这个加载请求时,才由子类加载器自身来加载该类。

类加载器层次结构

在 Java 中,类加载器按照层次结构组织,主要包括以下几种:

  1. 引导类加载器(Bootstrap ClassLoader)

    • 负责加载 :JVM 核心类库(如 rt.jar)。
    • 位置:通常由底层平台(如 JDK 的核心部分)实现,不是用 Java 编写的。
    • 代表:系统本身,没有父加载器。
  2. 扩展类加载器(Extension ClassLoader)

    • 负责加载 :Java 扩展库(位于 JAVA_HOME/lib/ext 目录下的类库)。
    • 父类加载器:引导类加载器。
    • 代表 :由 sun.misc.Launcher$ExtClassLoader 实现。
  3. 系统类加载器(System ClassLoader)(又称为应用类加载器):

    • 负责加载 :应用程序类路径(CLASSPATH)中的类库。
    • 父类加载器:扩展类加载器。
    • 代表 :由 sun.misc.Launcher$AppClassLoader 实现。
  4. 自定义类加载器

    • 开发者可自定义 :用户可以根据需要实现自己的类加载器,继承 java.lang.ClassLoader 类。

双亲委派模型的工作原理

双亲委派模型的基本工作流程如下:

  1. 类加载请求:当一个类加载器(子类加载器)收到类加载请求时,它首先不会自己尝试去加载这个类,而是将请求委派给它的父类加载器。
  2. 递归委派:父类加载器再将请求委派给它的父类加载器,依此类推,直到请求到达引导类加载器。
  3. 类加载 :引导类加载器尝试加载该类,如果加载成功,则返回该类的 Class 对象。
  4. 回退加载:如果引导类加载器无法加载该类,则回退到它的子类加载器(扩展类加载器),尝试加载,依此类推。如果所有父类加载器都无法加载该类,最终由子类加载器自己加载。

双亲委派模型示例

以下是一个简单的示例,展示了双亲委派模型的工作原理:

复制代码

java复制代码

public class ParentDelegationExample { public static void main(String[] args) { ClassLoader classLoader = ParentDelegationExample.class.getClassLoader(); while (classLoader != null) { System.out.println(classLoader); classLoader = classLoader.getParent(); } // 引导类加载器是由底层平台实现的,通常返回 null System.out.println(classLoader); } }

运行结果:

复制代码

复制代码

sun.misc.Launcher$AppClassLoader@18b4aac2 sun.misc.Launcher$ExtClassLoader@1b6d3586 null

双亲委派模型的优点

  1. 安全性 :防止核心类库(如 java.lang.Object 等)被自定义类覆盖,从而保护了核心类库的安全性。
  2. 避免重复加载:通过委派机制,确保每个类只会被加载一次,避免了类的重复加载。
  3. 类的统一性:确保同一个类在 JVM 中唯一性,保证了类加载的稳定和一致。

破坏双亲委派模型

尽管双亲委派模型有其显著优点,但在某些情况下,开发者可能需要打破这种模型。例如,某些框架(如 OSGi、Tomcat 等)需要在不同的类加载器中加载不同版本的同一个类。这时,可以通过自定义类加载器实现,但需要特别小心,避免引入类加载冲突和安全问题。

以下是一个简单的示例,展示如何自定义类加载器:

复制代码

java复制代码

public class CustomClassLoader extends ClassLoader { @Override protected Class<?> findClass(String name) throws ClassNotFoundException { // 自定义类加载逻辑,例如从文件系统或网络加载类 byte[] classData = loadClassData(name); if (classData == null) { throw new ClassNotFoundException(); } return defineClass(name, classData, 0, classData.length); } private byte[] loadClassData(String name) { // 自定义类加载逻辑 // 例如,读取 .class 文件并转换为字节数组 return null; } public static void main(String[] args) { try { CustomClassLoader customClassLoader = new CustomClassLoader(); Class<?> customClass = customClassLoader.loadClass("MyClass"); Object instance = customClass.newInstance(); System.out.println(instance.getClass().getName()); } catch (Exception e) { e.printStackTrace(); } } }

总结

双亲委派模型是 Java 类加载机制中的一个关键设计模式,通过委派机制确保类加载的一致性和安全性。理解和应用双亲委派模型对于开发高效、安全的 Java 应用程序至关重要。在特定情况下,可以通过自定义加载器来打破双亲委派模型,但需要特别注意类加载冲突和安全问题。

相关推荐
二哈赛车手4 小时前
新人笔记---ApiFox的一些常见使用出错
java·笔记·spring
栗子~~5 小时前
JAVA - 二层缓存设计(本地缓冲+redis缓冲+广播所有本地缓冲失效) demo
java·redis·缓存
YDS8295 小时前
DeepSeek RAG&MCP + Agent智能体项目 —— RAG知识库的搭建和接口实现
java·ai·springboot·agent·rag·deepseek
candyTong6 小时前
Claude Code 的 Edit 工具是怎么工作的
javascript·后端·架构
未若君雅裁6 小时前
MyBatis 一级缓存、二级缓存与清理机制
java·缓存·mybatis
AI人工智能+电脑小能手6 小时前
【大白话说Java面试题 第65题】【JVM篇】第25题:谈谈对 OOM 的认识
java·开发语言·jvm
GetcharZp7 小时前
GitHub 2.4 万 Star!D2 正在重新定义程序员画图方式
后端
阿维的博客日记7 小时前
Nacos 为什么能让配置动态生效?(涉及 @RefreshScope 注解)
java·spring
雨辰AI7 小时前
SpringBoot3 + 人大金仓读写分离 + 分库分表 + 集群高可用 全栈实战
java·数据库·mysql·政务
辰海Coding8 小时前
MiniSpring框架学习-完成的 IoC 容器
java·spring boot·学习·架构