搜索
您的当前位置:首页正文

JAVA SPI 和双亲委派的理解

来源:吉趣旅游网

双亲委派:在jvm加载class时需要使用类加载器进行加载,而在java中一共有3种:
Bootstrap Classloader 启动类加载器:负责加载/lib 下的核心类库,此加载器本身内嵌于JVM,在 Java 中找不到具体的引用,其是C++实现的;
Extension Classloader 扩展类加载器:负责加载/lib/ext 下的扩展类库;
Application Classloader 系统应用类加载器:负责-classpath 指定路径类库加载。
下层加载器在加载之前会移交给上层,上层没有才一级一级移交给下层加载,这样做的目的是保证了安全性和唯一性,比如我写个全限定名和jdk一样的String类,是否就破坏了系统代码?但由于双亲委派的存在加载String时会移交给最上层,最后再jdk包中就会找到正常jdk的String类避免程序员做手脚,另一方面在jvm中判断两个类是否一样除了全限定名还要看加载器,只有两个都一样时才能确认相等。
ContextClassLoader:这时一种特殊的类加载器,主要用于打破双亲委派,其实按我理解应该不是打破,而是绕开。
在SPI中核心类就是ServiceLoader ,通过它就可以加载接口的实现类这里面就涉及到了打破双亲委派,ServiceLoader有一个load方法使用到了ContextClassLoader:

    public static <S> ServiceLoader<S> load(Class<S> service) {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        // 使用当前线程的ClassLoader进行加载待加载的实现类
        return ServiceLoader.load(service, cl);
    }
 

这里的ServiceLoader是属于Boot加载器 所加载的类,而SPI实现类都是三方jar包,如果没有这里的打破双亲委派那么这里会报classnotfound的错,因在Boot所加载的包中是无法拿到app加载器所加载的类,打破双亲委派主要就是看contextclassloader,它会拿到实现类的加载器。

因篇幅问题不能全部显示,请点此查看更多更全内容

Top