なんとな~くしあわせ?の日記

「そしてそれゆえ、知識そのものが力である」 (Nam et ipsa scientia potestas est.) 〜 フランシス・ベーコン

SpringのDIとJavaのTimerによるオブジェクトの制御

???「設定ファイルに書いた通りのロジックで何らかの制御を行う何かを書けないか?」
俺「」


がんばった

使ったもの
・SpringのDI
JavaのTimer
ArrayList

ハマった所
xmlファイルのclassはパッケージ名から書かないとダメ
・総称型をArrayListに入れた後の処理

実行したら結構な勢いで標準出力にメッセージがでますので注意


ObjectFactory.java

package jp.gr.java_conf.nagata;

import java.util.ArrayList;
import java.util.Date;
import java.util.Timer;
import java.util.concurrent.TimeUnit;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ObjectFactory {

    public static void main(String args[]) {
	// アプリケーションコンテキストの取得
	ApplicationContext contxt = new ClassPathXmlApplicationContext("applicationContext.xml");

	// Beanの取得
	ArrayList<DoSomethingObject> somethingList = new ArrayList<DoSomethingObject>();
	somethingList = (ArrayList<DoSomethingObject>)contxt.getBean("somethings");
	System.out.println("タイマー始まるお~:" + new Date());

	// タイマーオブジェクトの配列
	ArrayList<Timer> timers = new ArrayList<Timer>();

	// オブジェクトの数だけタイマー起動する
	for (int i = 0; i < somethingList.size(); i++) {
	    System.out.println(somethingList.get(i).getStartMessage());
	    System.out.println(somethingList.get(i).getInterval());
	    Timer t = new Timer();
	    t.schedule(somethingList.get(i), 0, somethingList.get(i).getInterval());
	    timers.add(t);
        }

	// 3分間待ってやろう
	System.out.println("3分間待ってやろう:" + new Date());
	try {
	    TimeUnit.SECONDS.sleep(180);
	} catch (InterruptedException e) {
	    e.printStackTrace();
	}

	// オブジェクトの数だけタイマーを止める
	for (int i = 0; i < somethingList.size(); i++) {
	    System.out.println(somethingList.get(i).getStartMessage());
        }

	for (int i = 0; i < timers.size(); i++) {
	    timers.get(i).cancel();
	}

	System.out.println("タイマーやめる。。。人間にはできることとできないことがある:" + new Date());
    }
}

DoSomethingObject.java

package jp.gr.java_conf.nagata;

import java.util.TimerTask;

public class DoSomethingObject extends TimerTask {

    // コンストラクタ
    public DoSomethingObject() {}

    // 内部のプロパティ
    private String message;
    private String startMessage;
    private long interval;

    @Override
    public void run() {
	// タイマー実行時に呼ばれるメソッド
	System.out.println(message);
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getStartMessage() {
        return startMessage;
    }

    public void setStartMessage(String startMessage) {
        this.startMessage = startMessage;
    }

    public void setInterval(long interval) {
	this.interval = interval;
    }

    public long getInterval() {
	return interval;
    }

}

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<bean id="something1" class="jp.gr.java_conf.nagata.DoSomethingObject">
		<property name="message">
			<value>定時報告であります!</value>
		</property>
		<property name="startMessage">
			<value>タイマー起動であります!</value>
		</property>
		<property name="interval">
			<value>1</value>
		</property>
	</bean>

	<bean id="something2" class="jp.gr.java_conf.nagata.DoSomethingObject">
		<property name="message">
			<value>定時報告ですぞ!</value>
		</property>
		<property name="startMessage">
			<value>タイマー起動でありまぞ!</value>
		</property>
		<property name="interval">
			<value>2</value>
		</property>
	</bean>

	<bean id="something3" class="jp.gr.java_conf.nagata.DoSomethingObject">
		<property name="message">
			<value>定時報告ですわ!</value>
		</property>
		<property name="startMessage">
			<value>タイマー起動ですわ!</value>
		</property>
		<property name="interval">
			<value>3</value>
		</property>
	</bean>

	<bean id="something4" class="jp.gr.java_conf.nagata.DoSomethingObject">
		<property name="message">
			<value>bulletin</value>
		</property>
		<property name="startMessage">
			<value>Ya</value>
		</property>
		<property name="interval">
			<value>4</value>
		</property>
	</bean>

	<bean id="something5" class="jp.gr.java_conf.nagata.DoSomethingObject">
		<property name="message">
			<value>доброе утро</value>
		</property>
		<property name="startMessage">
			<value>да</value>
		</property>
		<property name="interval">
			<value>5</value>
		</property>
	</bean>

	<!-- ArrayListに格納 -->
	<bean id="somethings" class="java.util.ArrayList">
		<constructor-arg>
			<list>
				<ref bean="something1" />
				<ref bean="something2" />
				<ref bean="something3" />
				<ref bean="something4" />
				<ref bean="something5" />
			</list>
		</constructor-arg>
	</bean>
</beans>

同じことがCSVファイルでもできると聞いてやってみますた
Orange Signal CsvというApache 2.0ライセンスのライブラリを使った
OrangeSignal CSV - Java CSV ライブラリ

正直うちの会社で使ってるCSV処理をこれに変えたらわりと捗るんじゃないかと思った

ObjectFactory.java

package jp.gr.java_conf.nagata;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

import jp.sf.orangesignal.csv.Csv;
import jp.sf.orangesignal.csv.CsvConfig;
import jp.sf.orangesignal.csv.handlers.ColumnNameMappingBeanListHandler;

public class ObjectFactory {

    public static void main(String[] args) {

	CsvConfig cfg = new CsvConfig();
	cfg.setQuoteDisabled(false);                         // デフォルトでは無効となっている囲み文字を有効にします。
	cfg.setEscapeDisabled(false);                        // デフォルトでは無効となっているエスケープ文字を有効にします。
	cfg.setBreakString("\n");                            // 項目値中の改行を\nで置換えます。
	cfg.setNullString("NULL");                           // null値扱いする文字列を指定します。
	cfg.setIgnoreLeadingWhitespaces(true);               // 項目値前のホワイトスペースを除去します。
	cfg.setIgnoreTrailingWhitespaces(true);              // 項目値後のホワイトスペースを除去します。
	cfg.setIgnoreEmptyLines(true);                       // 空行を無視するようにします。
	cfg.setIgnoreLinePatterns(Pattern.compile("^#.*$")); // 正規表現による無視する行パターンを設定します(この例では#で始まる行)。
	//cfg.setSkipLines(1);                                 // 最初の1行目をスキップして読み込みます。

	// ファイルの読み込み処理
	FileInputStream is = null;
	try {
	    is = new FileInputStream("E:\\pleiades\\workspace\\ControlOrangeSignalObject\\src\\setting.csv");
	} catch (FileNotFoundException e1) {
	    e1.printStackTrace();
	}

	try {
	    List<DoSomethingObject> somethingList = Csv.load(is, cfg,
	            new ColumnNameMappingBeanListHandler<DoSomethingObject>(DoSomethingObject.class)
	                .addColumn("message", "message")
	                .addColumn("startMessage", "startMessage")
	                .addColumn("interval", "interval")
	        );

	    System.out.println("タイマー始まるお~:" + new Date());

	    // タイマーオブジェクトの配列
	    ArrayList<Timer> timers = new ArrayList<Timer>();

	    // オブジェクトの数だけタイマー起動する
	    for (int i = 0; i < somethingList.size(); i++) {
		System.out.println(somethingList.get(i).getStartMessage());
		System.out.println(somethingList.get(i).getInterval());
		Timer t = new Timer();
		t.schedule(somethingList.get(i), 0, somethingList.get(i)
			.getInterval());
		timers.add(t);
	    }

	    // 3分間待ってやろう(大嘘)
	    System.out.println("10秒待ってやろう:" + new Date());
	    try {
		TimeUnit.SECONDS.sleep(10);
	    } catch (InterruptedException e) {
		e.printStackTrace();
	    }

	    // オブジェクトの数だけタイマーを止める
	    for (int i = 0; i < somethingList.size(); i++) {
		System.out.println(somethingList.get(i).getStartMessage());
	    }

	    for (int i = 0; i < timers.size(); i++) {
		timers.get(i).cancel();
	    }

	    System.out.println("タイマーやめる。。。人間にはできることとできないことがある:" + new Date());
	} catch (IOException e) {
	    e.printStackTrace();
	}
    }

}

setting.csv

message,startMessage,interval
定時報告であります!,タイマー起動であります!,1
定時報告ですぞ!,タイマー起動でありますぞ!,2
定時報告ですわ!,タイマー起動ですわ!,3
bulletin,ya,4
доброе утро,да,5