Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在应用程序启动时动态触发对象方法_Java_Scala_Reflection - Fatal编程技术网

Java 在应用程序启动时动态触发对象方法

Java 在应用程序启动时动态触发对象方法,java,scala,reflection,Java,Scala,Reflection,我有一个应用程序,应该生产汽车,并与他们一起经营。汽车对象创建是一个复杂的过程,所以我需要一个工厂为每种类型的汽车。我还希望用户能够提供他们自己的汽车类型和生产它们的工厂。这些车型和工厂应该作为jar插入到我的应用程序中(可能有比jar更好的方法,但我看不到) 我有了一个想法,制作一个普通的汽车工厂,它接受汽车的名称(“梅赛德斯”、“宝马”、“尼桑”等)作为论据。CarFactory有一个映射,其中每个名称都映射到自己的factory类。代码看起来像这样(很抱歉,我无法提供工作副本,因为我仍在对

我有一个应用程序,应该生产汽车,并与他们一起经营。汽车对象创建是一个复杂的过程,所以我需要一个工厂为每种类型的汽车。我还希望用户能够提供他们自己的汽车类型和生产它们的工厂。这些车型和工厂应该作为jar插入到我的应用程序中(可能有比jar更好的方法,但我看不到)

我有了一个想法,制作一个普通的汽车工厂,它接受汽车的名称(“梅赛德斯”、“宝马”、“尼桑”等)作为论据。CarFactory有一个映射,其中每个名称都映射到自己的factory类。代码看起来像这样(很抱歉,我无法提供工作副本,因为我仍在对其进行评估,并且没有一个编译时没有错误的版本)

knownCarTypes是可变的,因为我希望用户工厂在此地图上注册,提供他们负责的汽车类型以及工厂类的名称。从用户类来看,它是这样的

class Mercedes extends Car

object MercedesFactory extends Factory {
  def register() {
    CarFactory.knownCarTypes("mercedes") = getClass
  }

  def create() = new Mercedes()
}
这是我的问题。我不知道如何触发用户工厂的register()方法。可能吗?有比我的方法更好的解决方案吗

我考虑为工厂创建公共trait,通过反射找到实现trait和trigger方法的所有加载类。但它看起来相当复杂。我希望这里可以使用一些设计模式或OOP技巧。你觉得怎么样


谢谢

如果我正确理解了您的问题,您所要做的就是从对象的“主体”调用register:


最后我通过反射使它工作起来。我迭代了指定路径上的所有JAR,找到了实现com.example.Factory trait的所有类,并触发了它们的register()方法。对于我使用的JAR检查和调用我遵循的对象方法,这里是最后的代码

import org.apache.commons.io.FileUtils
import org.clapper.classutil.{ClassFinder, ClassInfo}
import scala.collection.JavaConverters._

def triggerFactories() {
  val jars = FileUtils.iterateFiles(new File("lib"), Array[String]("jar"), true).asScala.toList
  val classes = ClassFinder(jars).getClasses
  val factories = ClassFinder.concreteSubclasses("com.example.Factory", classes)

  factories.foreach { (factory: ClassInfo) =>
    companion[Factory](factory.name).register()
  }
}

def companion[T](name: String)(implicit man: Manifest[T]): T =
  Class.forName(name).getField("MODULE$").get(man.erasure).asInstanceOf[T]

这对我有用。这看起来很棘手,但我希望它不会破坏我的应用程序在未来的任何东西。如果有更好的方法,请发帖,我会重新接受答案。

作为提示,如果您使用可变映射,则无需将其声明为变量。
+=
将对其进行适当的修改。哦。。你是对的。谢谢:)不幸的是,在我接触MercedesFactory对象之前(无论如何,通过调用其任何方法),它都不会调用对象体:(
object MercedesFactory extends Factory {
  def register() {
    CarFactory.knownCarTypes("mercedes") = getClass
  }
  register

  def create() = new Mercedes()
}
import org.apache.commons.io.FileUtils
import org.clapper.classutil.{ClassFinder, ClassInfo}
import scala.collection.JavaConverters._

def triggerFactories() {
  val jars = FileUtils.iterateFiles(new File("lib"), Array[String]("jar"), true).asScala.toList
  val classes = ClassFinder(jars).getClasses
  val factories = ClassFinder.concreteSubclasses("com.example.Factory", classes)

  factories.foreach { (factory: ClassInfo) =>
    companion[Factory](factory.name).register()
  }
}

def companion[T](name: String)(implicit man: Manifest[T]): T =
  Class.forName(name).getField("MODULE$").get(man.erasure).asInstanceOf[T]