[core] Support loading service from classloaders other than current (#2428)

* fix: load service, close #2268 #2427

* fix: check empty
This commit is contained in:
cssxsh 2023-02-17 17:57:12 +08:00 committed by GitHub
parent e686a23f40
commit 9f36eff070
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -16,6 +16,7 @@ import kotlin.reflect.full.createInstance
public actual fun <T : Any> loadService(clazz: KClass<out T>, fallbackImplementation: String?): T {
var suppressed: Throwable? = null
return ServiceLoader.load(clazz.java).firstOrNull()
?: ServiceLoader.load(clazz.java, clazz.java.classLoader).firstOrNull()
?: (if (fallbackImplementation == null) null
else runCatching { findCreateInstance<T>(fallbackImplementation) }.onFailure { suppressed = it }.getOrNull())
?: throw NoSuchElementException("Could not find an implementation for service class ${clazz.qualifiedName}").apply {
@ -29,10 +30,18 @@ private fun <T : Any> findCreateInstance(fallbackImplementation: String): T {
public actual fun <T : Any> loadServiceOrNull(clazz: KClass<out T>, fallbackImplementation: String?): T? {
return ServiceLoader.load(clazz.java).firstOrNull()
?: ServiceLoader.load(clazz.java, clazz.java.classLoader).firstOrNull()
?: if (fallbackImplementation == null) return null
else runCatching { findCreateInstance<T>(fallbackImplementation) }.getOrNull()
}
public actual fun <T : Any> loadServices(clazz: KClass<out T>): Sequence<T> {
return ServiceLoader.load(clazz.java).asSequence()
return sequence {
val current = ServiceLoader.load(clazz.java).iterator()
if (current.hasNext()) {
yieldAll(current)
} else {
yieldAll(ServiceLoader.load(clazz.java, clazz.java.classLoader))
}
}
}