SPI相關(guān)源碼分析
- ClassLoader
//F7單步執(zhí)行不會(huì)進(jìn)入,必須使用alt+shift+F7強(qiáng)制進(jìn)入
//AppClassLoader
loader.getResources(fullName);
//ExtClassLoader圆存、AppClassLoader都繼承UrlClassLoader再繼承ClassLoader店归,UrlClassLoader中包含UrlClassPath ucp字段,
//返回一個(gè)枚舉器(懶惰加載)醒叁,遍歷枚舉器時(shí)才會(huì)
Enumeration<Resource> e = UrlClassPath.getResources(String className)
//根據(jù)className遍歷loaders進(jìn)行加載
e.hasMoreElement()或e.next()
public Enumeration<URL> getResources(String name) throws IOException {
Enumeration<URL>[] tmp = (Enumeration<URL>[]) new Enumeration<?>[2];
if (parent != null) {
// AppClassLoader的parent為ExtClassLoader司浪,獲取其組合的枚舉器
tmp[0] = parent.getResources(name);
} else {
// ExtClassLoader的parent為null泊业,組合BootstrapResources
tmp[0] = getBootstrapResources(name);
}
tmp[1] = findResources(name);
return new CompoundEnumeration<>(tmp);
}
- CompoundEnumeration
private boolean next() {
//遍歷枚舉器數(shù)組找到滿足情況的枚舉
while(this.index < this.enums.length) {
if (this.enums[this.index] != null && this.enums[this.index].hasMoreElements()) {
return true;
}
++this.index;
}
return false;
}
- UrlClassPath
public Enumeration<Resource> getResources(final String var1, final boolean var2) {
return new Enumeration<Resource>() {
private int index = 0;
private int[] cache = URLClassPath.this.getLookupCache(var1);
private Resource res = null;
private boolean next() {
if (this.res != null) {
return true;
} else {
do {
URLClassPath.Loader var1x;
// UrlClassPath中包含ArrayList<URLClassPath.Loader> loaders字段,每個(gè)loader一般情況下是一個(gè)jarLoader,負(fù)責(zé)加載jar文件
if ((var1x = URLClassPath.this.getNextLoader(this.cache, this.index++)) == null) {
return false;
}
// 遍歷jarLoader啊易,確定其是否找到對(duì)應(yīng)的class
this.res = var1x.getResource(var1, var2);
} while(this.res == null);
return true;
}
}
- ServiceLoader
// ServiceLoader.LazyIterator
// 判斷迭代器中是否還有下一個(gè)服務(wù)
private boolean hasNextService() {
if (nextName != null) {
return true;
}
if (configs == null) {
// 組裝META-INF\services\className
String fullName = PREFIX + service.getName();
if (loader == null)
configs = ClassLoader.getSystemResources(fullName);
else
// 使用AppClassLoader生成枚舉器
configs = loader.getResources(fullName);
}
while ((pending == null) || !pending.hasNext()) {
//第一次進(jìn)入或當(dāng)?shù)谝粋€(gè)META-INF\services\className的file中的所有實(shí)現(xiàn)類已經(jīng)初始化完成后吁伺,繼續(xù)找其他的實(shí)現(xiàn)類file
if (!configs.hasMoreElements()) {
return false;
}
// 解析找到的包含了META-INF\services\className的file的URL,得到實(shí)現(xiàn)類名稱的迭代器
pending = parse(service, configs.nextElement());
}
// 返回實(shí)現(xiàn)類名稱
nextName = pending.next();
return true;
}
private S nextService() {
if (!hasNextService())
throw new NoSuchElementException();
String cn = nextName;
// 設(shè)置為null租谈,便于下一次hashNextService時(shí)得到下一個(gè)實(shí)現(xiàn)類的名稱
nextName = null;
Class<?> c = null;
// 找到實(shí)現(xiàn)類Class
//第二個(gè)參數(shù)表示是否執(zhí)行該class的初始化篮奄,初始化的概念如下
https://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4
Initialization of a class consists of executing its static initializers and the initializers for static fields (class variables) declared in the class.
Initialization of an interface consists of executing the initializers for fields (constants) declared in the interface.
c = Class.forName(cn, false, loader);
S p = service.cast(c.newInstance());
//放入providers數(shù)組中
providers.put(cn, p);
return p;
}
- DriverManager實(shí)踐
static {
loadInitialDrivers();
println("JDBC DriverManager initialized");
}
private static void loadInitialDrivers() {
//
ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
Iterator<Driver> driversIterator = loadedDrivers.iterator();
//找到下一個(gè)實(shí)現(xiàn)類
while(driversIterator.hasNext()) {
//初始化下一個(gè)實(shí)現(xiàn)類并放入ServiceLoader.providers中
driversIterator.next();
}
//第一次遍歷迭代器從lazyIterator中獲取對(duì)象并設(shè)置到providers中,再次初始化迭代器直接從providers中獲取對(duì)應(yīng)的實(shí)現(xiàn)類
//driversIterator = loadedDrivers.iterator();
}
//早期的jdbc使用方式
//注冊(cè) JDBC 驅(qū)動(dòng)
Class.forName(JDBC_DRIVER);
//不確定是如何使用注冊(cè)的Driver的
conn = DriverManager.getConnection(DB_URL,USER,PASS);
//后續(xù)的方式
//com.mysql.jdbc.Driver&org.postgresql.Driver都包含如下內(nèi)容
static {
//注冊(cè)自己的Driver到DriverManager.registeredDrivers(static)中
//由ServiceLoader中S p = service.cast(c.newInstance()),c為Driver對(duì)應(yīng)的Class割去,觸發(fā)行為
DriverManager.registerDriver(new Driver());
}
//DriverManager.getConnection()
//
for(DriverInfo aDriver : registeredDrivers) {
//測試使用postgrel的Driver去連mysql窟却,此處返回null
Connection con = aDriver.driver.connect(url, info);
if (con != null) {
// Success!
println("getConnection returning " + aDriver.driver.getClass().getName());
return (con);
}
}
- 不足
接口所有的實(shí)現(xiàn)類都newInstance()
ServiceLoader對(duì)多線程不夠友好