JVM(四)打破双亲委派和SPI机制

前言:

我们都知道判断两个类是不是同一个,要根据类加载器和全限定名。这是为什么呢?为什么不同的类加载器加载同一个类是不同的呢?

答案就是,不同的类加载器所加载的类在方法区的存储空间是不同的即InstanceKlass的不同。不同类加载器之间的空间是分隔开的。同一个类在一个类加载器中只会加载一次。

 双亲委派的弊端,无法做到不委派,也无法向下委派。

 

沙箱安全:

虽然JVM让我们用一些方式打破双亲委派,但是对于系统的核心类库JVM是会进行保护不让篡改的。如果自己写了和核心类库相同的类,在运行的时候会出错。

一:自定义类加载器打破双亲委派,不委派双亲

我们从上篇中有介绍classLoader.loadClass的时候会进行双亲委派进行加载,如果双亲都找不到指定类会调用findClass方法。

classLoader类中的loadClass有默认的实现就是双亲委派逻辑,findClass没有默认的实现需要自定义类加载器来实现。

所以如果只是使用一个自定义类加载器而不打破双亲委派,只要继承ClassLoader来重写findClass。如果想打破双亲委派,也要重写loadClass方法了,做到不委派。

二:SPI机制向下委派

SPI ,全称为 Service Provider Interface,是一种服务发现机制。它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类。

这一机制为很多框架扩展提供了可能,比如在Dubbo、JDBC中都使用到了SPI机制。我们先通过一个很简单的例子来看下它是怎么用的。SPI是实现向下委派的。

 

1:接口类模块

就一个接口,让其它模块通过Maven引用。

 

 

 2:第一个接口实现类模块

只有一个实现类,在resources下面增加META-INF/services文件夹,文件夹下面增加一个文本文件,文件名是实现的接口全路径,文件里面的内容是实现的类的全路径。

 

 

 

 

 3:第二个接口实现类模块

 

 

 

 

 

 

 

 

 

 接下来我们开始使用SPI机制

 

 

 我们在pom中引入第一个实现类模块:

上述main方法执行的结果就是对应实现类的执行结果。

 

当引入多个实现类的时候,都可以执行。

 

 

 

 

 

 

 

 

 

 

 

posted @ 2021-01-10 19:11  蒙恬括  阅读(1221)  评论(0编辑  收藏  举报