手写模拟tomcat类加载机制

public class TomcatClassLoaderDemo {
    public static void main(String[] args) throws Exception {
        URL[] commonUrls = new URL[]{new URL("/path/to/common")};
        // Common ClassLoader
        URLClassLoader commonClassLoader = new URLClassLoader(commonUrls, null);
        URL[] catalinaUrls = new URL[]{new URL("/path/to/catalina")};
        // Catalina ClassLoader  "/path/to/catalina"
        URLClassLoader catalinaClassLoader = new URLClassLoader(catalinaUrls, commonClassLoader);
        URL[] sharedUrls = new URL[]{new URL("/path/to/shared")};
        // Shared ClassLoader  "/path/to/shared"
        URLClassLoader sharedClassLoader = new URLClassLoader(sharedUrls, commonClassLoader);

        //模拟实现业务:假设在一个大型企业中,有多个Web应用部署在同一Tomcat服务器上。
        // 这些应用都使用了如Log4j或SLF4J这样的日志库。为了避免日志配置冲突或确保一致的日志格式,
        // 企业希望所有应用都使用相同版本的日志库。这样,它们就可以共享相同的日志配置,比如日志级别、
        // 格式化样式、输出目的地等。将这些日志库放在$CATALINA_BASE/lib中,并将delegate设置为true,
        // 可以确保所有Web应用都使用这些共享库,而不是各自携带的版本。
        // WebAppClassLoader
        WebDefineClassLoader webAppClassLoader1 = new WebDefineClassLoader("/path/to/webapp", sharedClassLoader);
        webAppClassLoader1.setDelegate(true);
        WebDefineClassLoader webAppClassLoader2 = new WebDefineClassLoader("/path/to/webapp", sharedClassLoader);
        webAppClassLoader2.setDelegate(true);
        // 使用WebAppClassLoader加载类
        Class<?> clazz = webAppClassLoader1.loadClass("com.example.MyClass");
        System.out.println("Loaded class: " + clazz.getName());

        /**
         * Delegate=false类加载器执行顺序
         * BootStrapClassLoader   ExtClassLoader     WebAppClassLoader   AppClassLoader  CommonClassLoader  SharedClassLoader  
         * Delegate=true类加载器执行顺序
         * BootStrapClassLoader   ExtClassLoader        AppClassLoader  CommonClassLoader  SharedClassLoader   WebAppClassLoader
         */
    }
}

class WebDefineClassLoader extends ClassLoader {
    private boolean delegate = false;

    public void setDelegate(boolean delegate) {
        this.delegate = delegate;
    }

    //("webDefineClassLoader",WebDefineClassLoader.class)
    Map<String, Class> resourceEntries = new ConcurrentHashMap<String, Class>();

    private String baseDir; // 类加载器的加载路径

    public WebDefineClassLoader(String baseDir, ClassLoader parent) {
        super(parent);
        this.baseDir = baseDir;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        // 这里简化处理,只按文件系统路径加载类文件
        byte[] classData = new byte[0];
        try {
            classData = loadClassData(name);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (classData == null) {
            throw new ClassNotFoundException();
        }
        return defineClass(name, classData, 0, classData.length);
    }


    private byte[] loadClassData(String name) throws Exception {
        // 从文件系统中加载类文件
        // 这里需要实现具体的文件读取逻辑,将.class文件读入字节数组
        String path = baseDir + name.replace(".", File.separator) + ".class";
        FileInputStream fileInputStream = new FileInputStream(path);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        int len = 0;
        while ((len = fileInputStream.read()) != -1) {
            byteArrayOutputStream.write(len);
        }
        fileInputStream.close();
        return byteArrayOutputStream.toByteArray();
    }


    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        //1.查找缓存
        Class aClass = resourceEntries.get(name);
        if (aClass != null) {
            return aClass;
        }
        //2.查找jdk缓存
        aClass = findLoadedClass(name);
        if (aClass != null) {
            return aClass;
        }
        //3.使用扩展类加载器,避免jdk类加载不到报错,跳过appClassLoader,避免干扰
        ClassLoader extClassLoader = getSystemClassLoader().getParent();
        aClass = extClassLoader.loadClass(name);
        if (aClass != null) {
            return aClass;
        }
        //4.如果delegate=true  委托父类  sharedClassLoader  CommonClassLoader  AppClassLoader
        if (delegate) {
            aClass = Class.forName(name, false, getParent());
        }
        if (aClass != null) {
            return aClass;
        }
        //5.先查找自己
        aClass = findClass(name);

        if (aClass != null) {
            return aClass;
        }
        //6.delegate=true 默认 委托父类  sharedClassLoader  CommonClassLoader  AppClassLoader
        if (!delegate) {
            aClass = Class.forName(name, false, getParent());
        }
        if (aClass != null) {
            return aClass;
        }
        throw new ClassNotFoundException(name);
    }
}

  • 11
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值