이것은 ServiceLoader
을위한 것입니다.
리플렉션 API를 사용하면 필요한 항목 (예 : 필터링은 물론 클래스 로더를 쿼리하지 않음)을 쉽게 분류 할 수 있다고 생각합니다.
"로드 된 클래스 검색"이란 실제로 이미로드 된 클래스를 의미합니다. 해당 클래스를 가져 오는 데는 this question을 참조하십시오.
당신이 알고있는 모든 위젯 클래스가로드되도록하는 이니셜 라이저가있는 위젯 라이브러리를 상상할 수 있습니다. 그런 다음 클라이언트는 이니셜 라이저 만 알아야합니다.
유형 테스트는 동일합니다. 당신이 형태 파라미터를 가지는 뭔가를 찾고있는
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"
}
:
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
}
샘플 :
[email protected] is what I need
[email protected] is not what I need, I'm looking for a widgets.Whatsit[widgets.Cog]
당신이
ServiceLoader
을 사용하고, 누가하지 않습니다 이후 10 년이 사건에
재 방문이 필요합니다.
[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
내용 :
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
}
스칼라와 자바 비교. getGenericInterfaces
에 LOC를 몇 개 넣었는지 알기를 원했고 스칼라에서 원하는 것을 찾았지만 운동을 마쳤습니다.
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}"
}
}
프로그래머가 인터페이스를 서비스로 명시 적으로 선언하고 모든 구현을 'META-INF/services/...'에 나열해야 할 필요가 없습니까? – ghik
예, 요점은 도서관에서 제공하는 내용을 알려주는 것입니다. 위젯을 위해 알려진 우주를 스캔하는 대신 알려진 위치에 주어진 클래스 로더를 쿼리 할 수있는 리소스가 있습니다. 나는 FYI 다른 조각을 붙였다. –
우수! 고마워요! 그게 내가 필요한 것입니다. – Doswell