
こんにちは。インテグレーションサービス本部の横山です。
Webアプリケーション以外の環境でSpringのBeanを起動したいとき、本格的なバッチ処理であればSpringBatchを使用するのが正解です。
が、そこまで大袈裟にしたくない場合に、mainメソッドから起動する方法を試してみました。
起動するBeanは以下のようなクラスです。サンプルなので、意味のある処理はしていません。コンソールにメッセージを出力するだけです。
【インターフェース】
package sample.springbeanrunner;
/*******************************************************************************
* 起動するビーンクラスのインターフェース。
******************************************************************************/
public interface TargetBean {
/*****************************************************************************
* 実行するメソッド。
****************************************************************************/
public void execute();
}
【実装クラス】
package sample.springbeanrunner;
/*******************************************************************************
* 起動するビーンクラス。
******************************************************************************/
public class TargetBeanImpl implements TargetBean {
/*****************************************************************************
* 実行するメソッド。
* @see sample.springbeanrunner.TargetBean#execute()
****************************************************************************/
@Override
public void execute() {
System.out.println("★★★ " + this.getClass().getName() + " が起動されました。");
}
}
このクラスを、mainメソッドから起動します。
コマンドライン引数に、ビーン設定ファイルのパス(オプション)、起動するビーンID(必須)を指定します。
パースには、Apache Commons CLIを使用しました。
【SpringBean起動クラス】
package sample.springbeanrunner;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.springframework.context.support.FileSystemXmlApplicationContext;
/*******************************************************************************
* SpringBean起動クラス。
******************************************************************************/
public class SpringBeanRunner {
/*****************************************************************************
* メイン処理。
****************************************************************************/
public static void main(String[] args) {
// コマンドライン引数をパースする。
CommandLine cmd = parseCommandLine(args);
// ビーン設定ファイル名を取得する。
// ※ コマンドライン引数から指定されないとき、省略時のビーン設定ファイル名を使用する。
String configLocation =
(cmd.hasOption("config") ? cmd.getOptionValue("config") : "app-config.xml");
// SpringFrameworkのビーンファクトリを準備する。
new FileSystemXmlApplicationContext(configLocation);
// 起動するBeanを取得する。存在しないとき、例外を投げる。
TargetBean target = ResourceFactory.getResource(cmd.getOptionValue("target"));
if (target == null) {
throw new RuntimeException("ビーン '" + cmd.getOptionValue("target") + "' が定義されていません。");
}
// 取得したBeanを実行する。
target.execute();
}
/*****************************************************************************
* コマンドライン引数をパースする。
****************************************************************************/
private static CommandLine parseCommandLine(String[] args) {
CommandLine ret = null;
// オプションのリストを生成する。
Options options = new Options();
// リストにオプションを追加する。
options.addOption(Option.builder("config").required(false).hasArg().argName("config")
.desc("ビーン設定ファイルのパス").build());
options.addOption(Option.builder("target").required().hasArg().argName("target")
.desc("起動するBeanID").build());
// コマンドラインをパースする。
CommandLineParser parser = new DefaultParser();
try {
ret = parser.parse(options, args);
}
catch (ParseException e) {
throw new RuntimeException(e);
}
return ret;
}
}
コマンドラインから指定されたビーンを取得するために、ビーン生成クラスを作ります。
インターフェース「org.springframework.context.ApplicationContextAware」を実装すると、Springが「org.springframework.context.ApplicationContext」を渡してくれます。
このApplicationContextのgetBeanメソッドを呼び出して、指定されたIDのビーンを取得します。
ビーン生成クラスはシングルトンとして、staticメソッドでアクセスできるようにしました。staticメソッドからアクセスするために、自分自身のインスタンスをstatic変数に格納しています。インスタンス化はSpringが行なうので、この格納は@postConstructを指定したメソッドで実行します。
【ビーン生成クラス】
package sample.springbeanrunner;
import javax.annotation.PostConstruct;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/*******************************************************************************
* ビーン生成クラス。
******************************************************************************/
public class ResourceFactory implements ApplicationContextAware {
/** 唯一のインスタンス */
private static ResourceFactory instance;
/** Springのアプリケーション設定。BeanFactoryとして必要。 */
private ApplicationContext applicationContext;
/*****************************************************************************
* リソースIDで識別される資源を取得する。
****************************************************************************/
public static <T> T getResource(String beanId) {
T ret = instance.doGetResource(beanId);
return ret;
}
/*****************************************************************************
* コンストラクタ実行後の後処理を行う。
****************************************************************************/
@PostConstruct
public void postConstruct() {
ResourceFactory.instance = this;
}
/*****************************************************************************
* Springのアプリケーション設定を設定する。
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
****************************************************************************/
@Override
public void setApplicationContext(ApplicationContext arg0) {
// Springのアプリケーション設定を設定する。
this.applicationContext = arg0;
}
/*****************************************************************************
* リソースIDで識別されるビーンを取得する。
****************************************************************************/
@SuppressWarnings("unchecked")
private <T> T doGetResource(String beanId) {
T ret = null;
try {
// 設定ファイルからクラスを検索する。
ret = (T)this.applicationContext.getBean(beanId);
}
catch (BeansException e) {
throw new RuntimeException(e);
}
return ret;
}
}
最後にビーン設定ファイル。
【ビーン設定ファイル】
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- コンポーネントを検索するクラスパス -->
<context:component-scan base-package="sample.springbeanrunner" />
<!-- ビーン生成クラス -->
<bean id="resourceFactory" scope="singleton"
class="sample.springbeanrunner.ResourceFactory">
</bean>
<!-- 起動するビーンクラス -->
<bean id="targetBean" scope="prototype"
class="sample.springbeanrunner.TargetBeanImpl">
</bean>
</beans>
こうして起点となるビーンさえ起動すれば、あとは通常のSpringと変わりません。