概要
実のところN番煎じではありますが……と言うかこの記事が無かった段階で試行錯誤していたのでベストプラクティスではないかも知れません。
ポイント
ComponentScanするクラスでの記述
/**
* 起動用クラス
* @author ysrken
*/
@ComponentScan
public class MainApp extends Application {
private static ConfigurableApplicationContext context;
/**
* main関数
* @param args コマンドライン引数
* @throws Exception 実行時例外
*/
public static void main(String[] args) throws Exception {
// このcontextは今後使い回すので、あえて上記のようにstatic変数にした
context = new AnnotationConfigApplicationContext(MainApp.class);
launch(args);
}
/**
* JavaFXの起動処理
* @param stage Stage情報
* @throws Exception 実行時例外
*/
public void start(Stage stage) throws Exception {
// 無難に生成するが、getBeanしているのがポイント
FXMLLoader loader = new FXMLLoader();
loader.setControllerFactory(MainApp.getApplicationContext()::getBean);
Parent rootNode = (Parent) loader.load(getClass().getResourceAsStream("/fxml/MainView.fxml"));
Scene scene = new Scene(rootNode);
stage.setScene(scene);
mainStage.show();
}
/**
* ApplicationContextを引き回すために使用
* @return 共用するApplicationContext
*/
public static ApplicationContext getApplicationContext() {
return context;
}
/**
* JavaFXの終了処理
* @throws Exception 実行時例外
*/
@Override
public void stop() throws Exception {
context.close();
}
}
ここで重要なのは「ConfigurableApplicationContext context
」の部分で、この変数をgetApplicationContext()
で他のウィンドウ生成時に利用します。
つまり、FXMLLoader
を利用する際、単にnew FXMLLoader()
とするだけではなく、loader.setControllerFactory(MainApp.getApplicationContext()::getBean);
としてcontextをセットしておきます。こうすることで、Spring FrameworkのDIがウィンドウのController
およびModel
にも及びます。
Controllerでの記述
@Component
//@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class Controller{
/**
* Model
*/
@Autowired
Model model;
/**
* 初期化
*/
public void initialize() {
~~~
}
}
前述のようにcontextをセットしておくことにより、@Autowired
するだけでModelが読み込まれます。当該ControllerおよびModelを複数個作成する予定がある場合は、SCOPE_PROTOTYPE
指定をしているコメントアウトを外しましょう。
Modelでの記述
@Component
//@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class Model{
/**
* 初期化
*/
publicModel() {
~~~
}
}
Modelでも@Autowired
が効くのは嬉しいですね。
その他での記述
DIしたいクラスにはだいたい@Component
等が付いていると思いますが、上記Controller関係以外で、内部に@Autowired
が使われているクラスのインスタンスを生成する際は次のように書きましょう。
@Component
public class SampleClass {
/**
* Model
*/
@Autowired
Hoge hoge;
~~~~~~
}
// OK
final SampleClass x = MainApp.getApplicationContext().getBean(SampleClass.class);
// NG
final SampleClass y = new SampleClass();