反射方法多次调用构造函数
Reflected Method calling constructor multiple times
我正在使用自定义 class 加载器和反射来启动 JavaFX GUI 应用程序,但是我似乎无意中多次调用了应用程序构造函数,这引发了异常(使用一种单例确保没有人尝试重新初始化主应用程序的模式 class).
当我从 Launcher
class.
调用 startupMethod.invoke(instance);
时,MyApp
构造函数的 IllegalStateException
被抛出
public class MyApp extends Application {
private static MyApp instance = null;
private static boolean started = false;
public MyApp() {
if (instance != null) {
throw new IllegalStateException("MyApp already initialized");
}
instance = this;
}
public static MyApp getInstance() {
return instance;
}
public void startup() {
synchronized (LOCK) {
if (started == true) {
throw new IllegalStateException("MyApp is already running");
}
}
// do things to start the GUI, etc...
// ... ... ...
started = true;
launch(); // static method part of the JavaFX platform
}
@Override
public void start(final Stage stage) {
// do stuff to display GUI
}
}
.
public class Launcher {
public static void main(String[] args) {
new Launcher().start();
}
private void start() {
// create custom classloader ...
// ... ... ...
Class<?> myAppClass = myLoader.loadClass("com.something.MyApp");
// calls the MyApp constructor and sets the "instance" static var to "this"
Object instance = myAppClass.newInstance();
Method startupMethod = myAppClass.getMethod("startup");
// this seems to call the MyApp constructor again!, exception thrown...
startupMethod.invoke(instance);
}
}
如果我在 MyApp
构造函数中注释掉异常,应用程序可以正常启动,但这意味着我仍然调用了构造函数两次,但我不确定为什么。我需要能够防止人们多次调用此构造函数。
EDIT:
通过一些研究,似乎对静态方法 Application.launch()
的调用试图在 JavaFX 应用程序线程上构建 MyApp
的新实例...
UPDATE:
已通过将静态方法添加到 MyApp
来修复,该方法仅调用 Application.launch()
方法。从 Launcher
class 我只是加载 MyApp
class 然后调用静态方法,如:
public class MyApp extends Application {
public MyApp() {
if (instance != null) {
throw new IllegalStateException("Already initialized");
}
instance = this;
}
// other stuff
public static void startup() {
launch();
}
}
.
public class Launcher {
// other stuff
Class<?> myAppClass = myLoader.loadClass("com.something.MyApp");
Method startupMethod = myAppClass.getMethod("startup");
startupMethod.invoke(null, null);
}
Application.launch()
创建调用它的 class 实例(必须是 Application
的子 class)。这就是第二个实例的来源。
我正在使用自定义 class 加载器和反射来启动 JavaFX GUI 应用程序,但是我似乎无意中多次调用了应用程序构造函数,这引发了异常(使用一种单例确保没有人尝试重新初始化主应用程序的模式 class).
当我从 Launcher
class.
startupMethod.invoke(instance);
时,MyApp
构造函数的 IllegalStateException
被抛出
public class MyApp extends Application {
private static MyApp instance = null;
private static boolean started = false;
public MyApp() {
if (instance != null) {
throw new IllegalStateException("MyApp already initialized");
}
instance = this;
}
public static MyApp getInstance() {
return instance;
}
public void startup() {
synchronized (LOCK) {
if (started == true) {
throw new IllegalStateException("MyApp is already running");
}
}
// do things to start the GUI, etc...
// ... ... ...
started = true;
launch(); // static method part of the JavaFX platform
}
@Override
public void start(final Stage stage) {
// do stuff to display GUI
}
}
.
public class Launcher {
public static void main(String[] args) {
new Launcher().start();
}
private void start() {
// create custom classloader ...
// ... ... ...
Class<?> myAppClass = myLoader.loadClass("com.something.MyApp");
// calls the MyApp constructor and sets the "instance" static var to "this"
Object instance = myAppClass.newInstance();
Method startupMethod = myAppClass.getMethod("startup");
// this seems to call the MyApp constructor again!, exception thrown...
startupMethod.invoke(instance);
}
}
如果我在 MyApp
构造函数中注释掉异常,应用程序可以正常启动,但这意味着我仍然调用了构造函数两次,但我不确定为什么。我需要能够防止人们多次调用此构造函数。
EDIT:
通过一些研究,似乎对静态方法 Application.launch()
的调用试图在 JavaFX 应用程序线程上构建 MyApp
的新实例...
UPDATE:
已通过将静态方法添加到 MyApp
来修复,该方法仅调用 Application.launch()
方法。从 Launcher
class 我只是加载 MyApp
class 然后调用静态方法,如:
public class MyApp extends Application {
public MyApp() {
if (instance != null) {
throw new IllegalStateException("Already initialized");
}
instance = this;
}
// other stuff
public static void startup() {
launch();
}
}
.
public class Launcher {
// other stuff
Class<?> myAppClass = myLoader.loadClass("com.something.MyApp");
Method startupMethod = myAppClass.getMethod("startup");
startupMethod.invoke(null, null);
}
Application.launch()
创建调用它的 class 实例(必须是 Application
的子 class)。这就是第二个实例的来源。