加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala – 动态对象/类加载

发布时间:2020-12-16 09:34:34 所属栏目:安全 来源:网络整理
导读:在Java中,通过这种方式加载外部类(在.jar文件中): ClassLoader classLoader = new URLClassLoader(new URL[] { new File("module.jar").toURI().toURL()});Class clazz = classLoader.loadClass("my.class.name");Object instance = clazz.newInstance();/
在Java中,通过这种方式加载外部类(在.jar文件中):

ClassLoader classLoader = new URLClassLoader(new URL[] {
  new File("module.jar").toURI().toURL()});
Class clazz = classLoader.loadClass("my.class.name");
Object instance = clazz.newInstance();

//check and cast to an interface,then use it
if (instance instanceof MyInterface)
  ...

它工作正常

====================

现在我想在Scala中做同样的事情。我有一个名为Module(Module.scala)的特质:

trait Module {
  def name: String
}

object Module {
  lazy val ModuleClassName = "my.module.ExModule"
}

我写了一个模块扩展模块,然后将其编译到module.jar中:

package my.module

import Module

object ExModule extends Module {}

然后我加载这个代码:

var classLoader = new URLClassLoader(Array[URL](
  new File("module.jar").toURI.toURL))
var clazz = classLoader.loadClass(Module.ModuleClassName)

工作正常但是如果我创建新的实例,我得到这个例外:

java.lang.InstantiationException: my.module.ExModule

如果我测试:

clazz.isInstanceOf[Module]

– >总是返回false。

那么你能帮我解决这个问题吗?

编辑

我猜是因为ExModule是一个对象(不是类)。但是当我将它改为class时,classLoader.loadClass(…)引发一个java.lang.NoClassDefFoundError。我猜这是因为ExModule从一个特质扩展了。

我很困惑。有人可以帮我吗

编辑

clazz.isInstanceOf[Class[Module]]//or Class[Byte],or Class[_]...

返回true。

解决方法

糟糕…我得到了答案。

借鉴:

> http://stackoverflow.com/a/8868537/942821(再次感谢Neil)。
> How do I call a Scala Object method using reflection?

====================

我猜这个方法是临时的,Scala团队提供正确的方式从外部jar文件加载一个对象/类/ trait …。还是因为我找不到正确的方法。但目前这有助于我解决问题。

var classLoader = new java.net.URLClassLoader(
  Array(new File("module.jar").toURI.toURL),/*
   * need to specify parent,so we have all class instances
   * in current context
   */
  this.getClass.getClassLoader)

/*
 * please note that the suffix "$" is for Scala "object",* it's a trick
 */
var clazzExModule = classLoader.loadClass(Module.ModuleClassName + "$")

/*
 * currently,I don't know how to check if clazzExModule is instance of
 * Class[Module],because clazzExModule.isInstanceOf[Class[_]] always
 * returns true,* so I use try/catch
 */
try {
  //"MODULE$" is a trick,and I'm not sure about "get(null)"
  var module = clazzExModule.getField("MODULE$").get(null).asInstanceOf[Module]
} catch {
  case e: java.lang.ClassCastException =>
    printf(" - %s is not Modulen",clazzExModule)
}

就这样 :-)

编辑

我最好设计ExModule作为一个类。从jar文件加载后,我可以像下面这样查看:

var clazz = classLoader.loadClass(Module.ModuleClassName)
if (classOf[Module].isAssignableFrom(clazz))
  ...

注意:

你不能做相反的方式:

if (clazz.isAssignableFrom(classOf[Module]))

因为Module是一个trait / object,所以在这种情况下isAssignableFrom()将不起作用。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读