spi
Spi是JAVA提供的一套用来被第三方实现或者扩展的API,spi机制是读取META-INF/services/目录下的元信息,然后ServiceLoader再根据元信息来加载对应的类。Spi规定如下:
①当服务提供者提供了接口的一种具体实现后,在jar包的META-INF/services目录下创建一个以“接口全限定名”命名的文件,文件内容则是实现类的全限定名。(注意接口与接口实现类)
②接口实现类所在的jar包放在主程序的classpath中。
③主程序通过java.util.ServiceLoader动态装载实现模块,通过扫描META-INF/services目录下的配置文件来找到实现类的全限定名,把类加载到JVM。
④spi的实现类必须有一个不带参数的构造方法。
说白了就是:META-INF/services目录下,有个接口全限定名命名的文件,该文件内容有2部分组成:接口定义、接口实现类。然后使用ServiceLoader来加载:
ServiceLoader<InterfaceA> load =
ServiceLoader.load(InterfaceA.class);
InterfaceAImpl aImpl = load.iterator().next();
aImpl.接口方法();
jar机制
jar包的META-INF/MAINFEST.MF文件包含了jar的元信息,例如:Mainifest-Version用来定义manifest文件版本,Main-Class定义jar文件的入口类(该类必须是一个可执行类,一旦定义了该属性就可以通过java -jar x.jar来运行该jar文件)、Class-Path指定该jar包所依赖的外部jar包、签名相关属性。
JAVA中类加载器分为3个:
①BootstrapClassLoader加载JAVA_HOME/jre/lib下部分jar包。
②ExtClassLoader加载JAVA_HOME/jre/lib/ext下面的jar包。
③AppClassLoader加载用户自定义classpath/jar包中Class-Path定义的第三方jar包。
类的生命周期为:加载Loading、验证Verification、准备Preparation、解析Resolution、初始化Initialization、使用Using、卸载Unloading。当遇到java -jar命令时jar文件则以二进制流的形式被读取到内存,然后类会在一个合适的时机从内存加载到虚拟机JVM中,而类的加载时机如下:
①遇到new、getstatic、putstatic、invokestatic这4条字节码指令时,如果类没有进行过初始化,则需要先对其进行初始化,这4条指令最常见的JAVA代码场景就是new实例化对象、读取/设置一个static字段、调用static方法的时候。
②使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。
③当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
④当JVM启动时,用户需要指定一个要执行的主类(即包含main()方法的那个类),JVM会先初始化这个主类。
当触发类加载的时候,类加载器也不是直接加载这个类,
第一步:查看AppClassLoader有没有加载过这个类,如果加载过则直接拿出来,无需再次加载。如果没有加载则进行下一步。
第二步:查看ExtClassLoader有没有加载过这个类,如果加载过则直接拿出来,无需再次加载。如果没有加载则进行下一步。
第三步:查看BootstrapClassLoader,如果加载过则直接拿出来,无需再次加载。如果没有加载则进行上一步直到AppClassLoader确保类只会被加载一次。
本文深入探讨了Java SPI机制的工作原理,包括如何通过META-INF/services目录下的元信息动态加载接口实现类,以及类加载器如何按特定顺序加载类。同时,文章详细解释了类的生命周期,从加载到卸载的各个阶段。
787

被折叠的 条评论
为什么被折叠?



