开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 21 天,点击查看活动详情
ServiceLoader相关内容
前文
本文主要内容是关于java的一个类加载器ServiceLoader的相关内容的总结。
ServiceLoader是什么
类似于classLoader负责在程序初始化阶段的类的加载,serviceLoader也是一个简单的服务提供类加载器,主要作用是将类从文件中加载到程序中,类生命周期的第一阶段。与classLoader有所不同,classLoader可以加载所有类型的类,而serviceLoader实际上主要是用来加载某种类型的类或其子类,也就是加载某个类的子类或某个接口的实现类,这些类一般具有同样的特征或逻辑意义。
ServiceLoader的应用
提到serviceLoader,其实在数据库连接的驱动初始化场景中有所应用,也就是java中所提供的DriverManager类中。通过serviceLoader的加载,可以直接将系统中所引入的所有java.util.Driver的驱动类加载到程序当中,用于作为后续的数据库连接驱动。
ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
Iterator<Driver> driversIterator = loadedDrivers.iterator();
try{
while(driversIterator.hasNext()) {
driversIterator.next();
}
} catch(Throwable t) {
// Do nothing
}
return null;
如上述代码所示,如果系统中引入了若干的数据库驱动类,且未进行手动的加载初始化,serviceLoader会通过接口进行加载,并对加载的结果进行递归处理。而在递归中,实际上则进行类的初始化操作,下面是递归时所具体执行的内容:
private S nextService() {
if (!hasNextService())
throw new NoSuchElementException();
String cn = nextName;
nextName = null;
Class<?> c = null;
try {
c = Class.forName(cn, false, loader);
} catch (ClassNotFoundException x) {
fail(service,
"Provider " + cn + " not found");
}
if (!service.isAssignableFrom(c)) {
fail(service,
"Provider " + cn + " not a subtype");
}
try {
S p = service.cast(c.newInstance());
providers.put(cn, p);
return p;
} catch (Throwable x) {
fail(service,
"Provider " + cn + " could not be instantiated",
x);
}
throw new Error(); // This cannot happen
}
如上面的代码所以,实际上将数据库连接驱动加载后,会在递归的过程中进行驱动类的初始化相关操作,将驱动类初始化到系统之中。这样当后续进行数据库的连接处理时,将连接信息传递到数据库驱动管理类后,会进行实际所采用的数据库匹配,找到可采用的数据库驱动,进行后续的数据库连接、操作等处理。
对于平时的使用,我们也完全可以利用serviceLoader进行类的加载处理及初始化操作。但是使用时要注意的是,所采用的类型必须要具备无参数构造方法,实际上该类在加载器的加载过程中执行的是无参的默认构造方法。主要的应用场景则是对于一类接口的实例化处理。
总结
本文主要是介绍了serviceLoader相关知识及其应用的相关内容。