Main 中不允许覆盖修饰符,但是当我在 Scala 中扩展 App 特征时允许覆盖修饰符

Override modifier is not allowed in Main however it is allowed when I extend App trait in scala

我正在尝试为我的应用程序创建启动器程序,并且正在通过 App 特征和 main 方法来决定使用哪一个。我在两者之间发现的唯一 difference 是:

(1) Threaded code that references the object will block until static initialization is complete. However, because the entire execution of an object extending Application takes place during static initialization, concurrent code will always deadlock if it must synchronize with the enclosing object.

在我的例子中,我有一个 Launcher,它基本上初始化了一个 Kafka 加载器对象,该对象保持 运行 kafka 轮询。下面是我的 Launcher 特征:

trait Launcher extends LazyLogging {
val config: Config
val actorSystem: ActorSystem
val sourceMessagesType = config.getString("app.source.dataType")
val targetTopic = config.getString("app.kafka.targetTopic")
val targetTopicPartitions =config.getInt("app.kafka.targetTopicPartitions")

val routingManager = HashedPartitionRoutingManager(targetTopic, targetTopicPartitions)
logger.info(s"Initializing MorpheusStreamDataLoader for $sourceMessagesType type")
sourceMessagesType.toLowerCase match {
case "json" => JSonDataLoader(config, routingManager)
case "avro" => AvroDataLoader(config, routingManager)
case _ => throw new IllegalArgumentException
  s"Messages of type ${sourceMessagesType.toLowerCase} are not supported.\n" 
 }
}

现在启动我的应用程序,我试图找到最适合使用的方法,Appmain 方法。但是 main 方法实现根本不起作用:

object ClientLauncher extends  Launcher {
def main(args: Array[String]): Unit = {
override val config=ConfigFactory.load(args(0))
override val actorSystem: ActorSystem=ActorSystem("ClientActorSystem")
 }
}

当我这样做时,我在 override 修饰符 override modifier is not allowed here 上出错。但是,如果我使用 App 特性,它不会给我任何编译时错误。

object ClientLauncher extends App with Launcher {
override val config=ConfigFactory.load(args(0))
override val actorSystem: ActorSystem=ActorSystem("ClientActorSystem")
}

我在阅读了几篇关于 App trait 和 main 的帖子后得到的信息是,除了我们使用 App trait 时发生的延迟初始化外,没有其他区别.为什么 override 不适用于 main 方法而适用于 App?我启动应用程序的最佳方式是什么?

您需要将它们移到方法之外,使它们成为对象字段而不是局部变量。

object ClientLauncher extends  Launcher {

  override val config=ConfigFactory.load()
  override val actorSystem: ActorSystem=ActorSystem("ClientActorSystem")

  def main(args: Array[String]): Unit = {
    /*code*/
  }
}

尽管如此,您将无法访问命令行参数或 main 本地的任何其他内容。

如果您需要访问它并且不想扩展应用程序,另一种方法是使用单独的 class 来扩展启动器。

class ClientLauncher(configFile: String) extends  Launcher {
  override val config=ConfigFactory.load(configFile)
  override val actorSystem: ActorSystem=ActorSystem("ClientActorSystem")
}

object Main {
  def main(args: Array[String]): Unit = {
    new ClientLauncher(args(0))
  }
}

或者将这些参数作为系统属性而不是命令行参数传递。

object ClientLauncher extends  Launcher {

  override val config=ConfigFactory.load(sys.props("configFile"))
  override val actorSystem: ActorSystem=ActorSystem("ClientActorSystem")

  def main(args: Array[String]): Unit = {
    /*code*/
  }
}

并在您运行您的代码

时传入系统属性
java -DconfigFile="config.conf" -jar myJar.jar