技术研究:Tomcat是如何打破双亲委派机制的实现应用程序的类库相互隔离

Tomcat 打破双亲委派机制的目的其实很简单,我们知道 Web 容器可能是需要部署多个应用程序的。但是假设不同的应用程序可能会同时依赖第三方类库的不同版本。我们知道类加载的时候要确保唯一性的,但是总不能要求同一个类库在 Web 容器中只有一份吧?所以 Tomcat 就需要保证每个应用程序的类库都是相互隔离并独立的,这也是它为什么打破双亲委派机制的主要目的。实现 Web 应用程序之间的类加载器相互隔离独立的是 WebAppClassLoader 类加载器。它为什么可以隔离每个 Web 应用程序呢?原因就是它打破了"双亲委派"的机制,如果收到类加载的请求,它会先尝试自己去加载,如果找不到在交给父加载器去加载,这么做的目的就是为了优先加载 Web 应用程序自己定义的类来实现 Web 应用程序相互隔离独立的。

如何打破?继承 ClassLoad 重写 findClass()。

// Tomcat 打破双亲委派机制的伪代码样例

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

public class WebappClassLoader extends URLClassLoader {

    // 存储已经加载的类,以避免重复加载
    private final Map<String, Class<?>> loadedClasses = new HashMap<>();

    // 构造函数,接受类路径的 URL 数组
    public WebappClassLoader(URL[] urls) {
        super(urls);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        // 第一步: 检查类是否已经被加载
        Class<?> clazz = loadedClasses.get(name);
        if (clazz != null) {
            return clazz;
        }

        // 第二步: 尝试使用自定义逻辑加载类
        try {
            // 在这里可以实现自定义的类加载逻辑
            // 为简化示例,这里直接调用父类的方法
            clazz = super.findClass(name);
            loadedClasses.put(name, clazz); // 将加载的类缓存起来
            return clazz;
        } catch (ClassNotFoundException e) {
            // 第三步: 如果未找到,委托给父类加载器
            return super.findClass(name);
        }
    }

    @Override
    public Enumeration<URL> getResources(String name) throws IOException {
        // 自定义资源加载的实现
        return super.getResources(name);
    }
    
    // 可以根据需要重写更多的方法

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
双亲委派机制(Parent-Delegation Model)是Java类加载器体系结构中的一项重要设计,它的工作原理是在类被请求时,先由当前类加载器寻找,如果找不到再委托给父级加载器查找。这样做的好处主要有: 1. 安全性:防止恶意代码替换系统类库,因为每个类加载器只负责加载自己的路径下的类。 2. 隔离性:避免类名冲突,子类加载器不会覆盖父加载器已经加载过的类。 然而,有时可能需要打破这种机制,比如: 1. 自定义类加载:当开发者希望在特定环境或上下文中动态加载类,例如Web应用程序中的Spring框架或第三方库可能需要自定义类加载策略。 2. 组合加载器:为了兼容多个版本的库或者需要处理不同版本之间的依赖冲突。 Tomcat作为Java Web应用服务器,提供了几种方法来打破双亲委派机制: 1. 使用`java.lang.instrument包`:这个API允许动态修改运行时类文件,可以在应用启动后,通过ClassFileTransformer接口改变类加载行为。 2. 在web.xml中配置`<loader>`元素:对于Servlet或JSP等资源,可以通过 `<Context>` 标签内的 `<Loader>` 元素来指定一个非标准的类加载器,如`org.springframework.web.context.support.AnnotationConfigWebApplicationContext$AnnotationConfigwarClassLoader`。 3. 使用`WebappLoader`或`CustomClassLoader`:这些类允许创建一个自定义的类加载器,用于Tomcat应用中的某个特定区域。 总之,打破双亲委派机制是为了满足特殊需求,但在实际操作中需要谨慎,因为它可能会引入安全风险和复杂性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值