类加载和spi发现机制杂谈

49 阅读1分钟

曾经觉得项目中的AppClassLoader就可以加载src和maven jar中的类,为什么还需要serviceLoader,既然都可以加载类为什么不直接用AppClassLoader加载,是不是有点多余。

一.先理解项目中这两种类加载器加载过程:

1.项目启动时,比如idea启动项目,idea会创建类似java -jar xxApplication.class 命令(类似我们部署服务),实际classpath会囊括src和maven管理的jar, 路径的所有类在被使用时(延迟加载)就会通过AppClassLoader加载。

2.类是用到才加载,那么要使用serviceloader加载类,还得使用spring的注入机制,或者显式调用serviceLoader.load()才会加载类,否则就还是AppClassLoader加载;或者配合工厂模式,使用@configuration和@Bean调用工厂类,在工厂类中显式调用serviceLoader.load();

二.serviceLoader加载的好处

1.serviceLoader.load(接口类.class),允许不同的实现类在不同的jar,实现解耦,只要遵循注册文件格式和位置(文件名为接口名,内容为实现类的权限定名;位置为/META-INFO/services)即可读取加载不同jar的/META-INFO/services位置中的类

2.类只会在使用时被加载一次,当serviceLoader加载完一个类后,该类不会再被AppClassLoader加载,因此spi模式除了实现类的加载,还实现了解耦和动态加载,在多方协作开发中是很有必要的。比如jdbc的Driver就是spi方式通过DriverManager注册的时候调用serviceLoader.load(Driver.class)加载不同的驱动jar中的META-INFO/services的现实类进行扩展的。实际这种加载打破了双亲委派的加载方式,目的还是让项目的扩展更灵活和解耦。