Đây là những gì ServiceLoader
dành cho.
Tôi nghĩ rằng API phản chiếu giúp bạn dễ dàng phân loại những gì bạn cần (tức là, để lọc nhưng không phải để truy vấn trình tải lớp).
Nếu, theo cụm từ của bạn, "tìm kiếm các lớp đã tải", bạn thực sự có nghĩa là các lớp đã được tải, hãy xem this question để nhận chúng.
Bạn có thể tưởng tượng một thư viện tiện ích con bằng trình khởi tạo chỉ đảm bảo rằng tất cả các lớp tiện ích mà nó biết đều được tải. Sau đó, khách hàng chỉ cần biết trình khởi tạo.
Kiểm tra loại giống nhau.
val need = typeOf[Whatsit[Cog]]
for (x <- (ServiceLoader load classOf[Whatsit[_]]).asScala) {
val im = currentMirror reflect x
if (im.symbol.toType weak_<:< need)
Console println s"$x is what I need"
else
Console println s"$x is not what I need, I'm looking for a $need"
}
Trong trường hợp bạn đang tìm kiếm một cái gì đó với các thông số type:
trait Whatsit[+A <: Widget] {
def widget: A
}
class Engine extends Whatsit[Cog] {
def widget = new Cog
}
class FlyWheel extends Whatsit[Sprocket] {
def widget = new Sprocket
}
mẫu:
[email protected] is what I need
[email protected] is not what I need, I'm looking for a widgets.Whatsit[widgets.Cog]
Trong trường hợp nó được mười năm kể từ khi bạn sử dụng ServiceLoader
, và ai không cần bồi dưỡng:
[email protected]:~/tmp$ ls -R META-INF
META-INF:
MANIFEST.MF services
META-INF/services:
widgets.Whatsit widgets.Widget
[email protected]:~/tmp$ cat META-INF/services/widgets.Widget
widgets.Cog
widgets.Sprocket
[email protected]:~/tmp$ cat META-INF/services/widgets.Whatsit
widgets.Engine
widgets.FlyWheel
Stuff:
package widgets
trait Widget {
def turn(): Int
override def toString = s"Widget ${getClass.getSimpleName}"
}
class Cog extends Widget {
def turn() = 5
}
class Sprocket extends Widget {
def turn() = 10
}
trait Whatsit[+A <: Widget] {
def widget: A
override def toString = s"Whatsit ${getClass.getSimpleName} of $widget"
}
class Engine extends Whatsit[Cog] {
def widget = new Cog
}
class FlyWheel extends Whatsit[Sprocket] {
def widget = new Sprocket
}
So sánh Scala và Java. Tôi sẽ có được một cảm giác có bao nhiêu LOC để getGenericInterfaces
và tìm thấy những gì bạn muốn trong Scala, nhưng sau đó tôi chấm dứt tập thể dục.
package findwidgets
import reflect._
import reflect.runtime.universe._
import reflect.runtime.currentMirror
import scala.collection.JavaConverters._
import java.util.ServiceLoader
object Test extends App {
import widgets.{ Widget, Whatsit, Cog }
val ws = (ServiceLoader load classOf[Widget]).asScala
for (w <- ws) {
Console println s"Turn a ${w.getClass} by ${w.turn}"
}
val need = typeOf[Whatsit[Cog]]
for (x <- (ServiceLoader load classOf[Whatsit[Cog]]).asScala) {
val im = currentMirror reflect x
if (im.symbol.toType weak_<:< need)
Console println s"$x is what I need"
else
Console println s"$x is not what I need, I'm looking for a $need"
// java says:
if (classOf[Whatsit[Cog]] isAssignableFrom x.getClass)
Console println s"Um, OK, I'll take the $x"
else
Console println s"${classOf[Whatsit[Cog]]} isn't ass'able from ${x.getClass}"
}
}
Điều này không yêu cầu người lập trình tuyên bố rõ ràng giao diện của mình dưới dạng dịch vụ và liệt kê tất cả các triển khai của nó trong 'META-INF/services/...'? – ghik
Có, do đó, điểm là thư viện cho bạn biết những gì nó cung cấp. Thay vì cố gắng quét vũ trụ đã biết cho các widget, có một tài nguyên ở một vị trí đã biết mà bạn có thể truy vấn cho một trình nạp lớp đã cho. Tôi dán các phần khác FYI. –
Tuyệt vời! Cảm ơn som! Đó chính xác là những gì tôi cần. – Doswell