动态类加载Scala类型
我有以下Scala类层次结构:动态类加载Scala类型,scala,classloader,Scala,Classloader,我有以下Scala类层次结构: abstract class BaseModule(val appConf : AppConfig) { // ... } class SimpleModule(appConf : AppConfig) extends BaseModule(appConf) { // ... } class FairlyComplexModule(appConf : AppConfig) extends BaseModule(appConf) { // ... }
abstract class BaseModule(val appConf : AppConfig) {
// ...
}
class SimpleModule(appConf : AppConfig) extends BaseModule(appConf) {
// ...
}
class FairlyComplexModule(appConf : AppConfig) extends BaseModule(appConf) {
// ...
}
// dozens of other BaseModule subclasses...
在运行时,我的应用程序将为要实例化的BaseModule
子类的完全限定类名接受一个字符串输入参数,但代码不知道它将是哪个具体的子类。因此,我:
val moduleFQCN = loadFromInputArgs() // ex: "com.example.myapp.SimpleModule"
val moduleClass = Class.forName(moduleFQCN)
println(s"Found ${moduleFQCN} on the runtime classpath.")
val module = Class.forName(moduleFQCN).getConstructor(classOf[AppConfig]).newInstance(appConf).asInstanceOf[BaseModule]
这样,输入指定在类路径上查找哪个BaseModule
子类,然后实例化。上面的前三行执行得很好,我看到println
fire。但是,上面的最后一行引发异常:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
<rest of stacktrace omitted for brevity>
线程“main”java.lang.reflect.InvocationTargetException中的异常
位于sun.reflect.NativeConstructorAccessorImpl.newInstance0(本机方法)
位于sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
很明显,当我试图创建
SimpleModule
子类的实例时,我做了一些错误的事情,只是不知道它是什么。有什么想法吗?您可能失败了,因为您在没有任何参数的情况下调用了newInstance()
,但是没有找到默认构造函数,因此实例化失败
试试这个:
Class.forName(moduleFQCN).getConstructor(classOf[AppConfig])
.newInstance(appConf).asInstanceOf[BaseModule]
其中
appConf
是AppConfig
的实例,是实例化BaseModule
的参数。您可能会失败,因为您调用newInstance()
时没有任何参数,但没有找到默认构造函数,因此实例化失败
试试这个:
Class.forName(moduleFQCN).getConstructor(classOf[AppConfig])
.newInstance(appConf).asInstanceOf[BaseModule]
其中
appConf
是AppConfig
的一个实例,是实例化BaseModule
的参数。谢谢@Alon Segal(+1)我想您已经了解了默认构造函数的一些内容,但是您使用简单字符串的示例对我没有帮助。我认为另一个复杂的因素是代码知道需要一些BaseModule
subclass,但在运行时才需要。如果您可以将您的示例更改为使用我的BaseModule
用例,并且对我有效,我将很高兴地给您绿色支票!再次感谢!再次感谢(+1),我想我们离得越来越近了,但还不是很近。请查看我更新的问题/代码片段和正在生成的新异常(InvocationTargetException
)。思想?再次非常感谢!我正试图重现您的错误,您能告诉我引发异常的“moduleFQCN”的值吗?这可能是因为异常是从您试图实例化的构造函数中引发的…感谢@Alon Segal(+1)我想您已经了解了默认构造函数的一些内容,但是,您使用简单字符串的示例对我没有帮助。我认为这里的另一个复杂因素是代码知道需要一些BaseModule
子类,但直到运行时才知道。如果您可以将您的示例更改为使用我的BaseModule
用例,并且对我有效,我将很高兴地给您绿色支票!再次感谢!再次感谢(+1),我想我们离得越来越近了,但还不是很近。请查看我更新的问题/代码片段和正在生成的新异常(InvocationTargetException
)。思想?再次非常感谢!我正在试图重现您的错误,您能告诉我引发异常的“moduleFQCN”的值吗?这可能是因为异常是从您试图实例化的构造函数中引发的……作为引发异常的InvocationTargetException
检查通过getCause()引发的实际异常
首先。检查appConfig
在调用时是否有效。您正在实例化的类的构造函数可能正在引发异常。从fornewInstance
:@throws InvocationTargetException-如果基础构造函数引发异常
,则您给出的代码不是问题,相反,在对象创建过程中存在一个问题。为了取得更大的进步,您应该向我们提供所有令人不快的堆栈跟踪或更多的真实代码。+1至rxg
的评论:阿隆的回答解决了您发布的问题;为了解决您的新问题,我们需要堆栈跟踪中的内部异常,您在堆栈跟踪中发布了“为简洁起见省略了stacktrace的其余部分”。使用scala.reflect.internal.util.scalacsloader.create(fqcn,onError)
,您可能会得到更好的ergnonomics。使用ScalaClassLoader.apply(classLoader)
。作为导致异常的InvocationTargetException
a,首先检查通过getCause()引发的实际异常。检查appConfig
在调用时是否有效。您正在实例化的类的构造函数可能正在引发异常。从fornewInstance
:@throws InvocationTargetException-如果基础构造函数引发异常
,则您给出的代码不是问题,相反,在对象创建过程中存在一个问题。为了取得更大的进步,您应该向我们提供所有令人不快的堆栈跟踪或更多的真实代码。+1至rxg
的评论:阿隆的回答解决了您发布的问题;为了解决您的新问题,我们需要堆栈跟踪中的内部异常,您在堆栈跟踪中发布了“为简洁起见省略了stacktrace的其余部分”。使用scala.reflect.internal.util.scalacsloader.create(fqcn,onError)
,您可能会得到更好的ergnonomics。使用ScalaClassLoader.apply(classLoader)
创建它。