今回はbeanのスコープについてのお話です。
beanのスコープというのは、Springが、どの範囲でbeanのインスタンスを生成・破棄するかを指定するものになります。
Spring Framework2.5では、以下の5つのスコープがあります。
- singleton
1つのコンテナ内で1つのインスタンス(デフォルトはこれになる) - prototype
コンテナからbeanを取得するたびにインスタンスを生成する - request
Webアプリ専用。HTTPのRequest単位でインスタンスを生成する。 - session
Webアプリ専用。HTTPのSession単位でインスタンスを生成する。 - global session
ポートレット専用。詳しくないのでよくわからない。グローバルセッションというものがあるらしい。
3以降は、Web系でしか使えないので、コンソールアプリとかで少し試すぶんにはsingletonとprototypeの2つになります。
今回は、この2つの動きについて見ていこうと思います。残りの部分については、勧めていく過程で使えるようになったら使っていきます。
Springがインスタンスを生成したことがわかるように、コンストラクタにログを吐くように作ったクラスを1つ定義します。
springscope/MyBean.java
package springscope;
public class MyBean {
public MyBean() {
System.out.println("MyBean コンストラクタ");
}
public void execute() {
System.out.println("MyBean#execute()実行");
}
}
これをSpringに登録して、singletonとprototypeで出力されるメッセージの違いを観察します。
スコープの指定は、Springの定義ファイルで、beanタグにscope属性として指定します。
application.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!-- プロトタイプ -->
<bean id="prototypeBean" class="springscope.MyBean" scope="prototype" />
<!-- シングルトン(scope属性を省略しても同じ) -->
<bean id="singletonBean" class="springscope.MyBean" scope="singleton" />
</beans>
この定義ファイルを読み込んでごにょごにょやるプログラムを書きます。
package springscope;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
System.out.println("ApplicationContextを作成");
System.out.println("======================================");
ApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml");
System.out.println("プロトタイプのBeanを2つ取得");
MyBean prototype1 = (MyBean) ctx.getBean("prototypeBean");
MyBean prototype2 = (MyBean) ctx.getBean("prototypeBean");
System.out.println("処理を実行");
prototype1.execute();
prototype2.execute();
System.out.println("======================================");
System.out.println("シングルトンのBeanを2つ取得");
MyBean singleton1 = (MyBean) ctx.getBean("singletonBean");
MyBean singleton2 = (MyBean) ctx.getBean("singletonBean");
System.out.println("処理を実行");
singleton1.execute();
singleton2.execute();
}
}
これを実行して、動きを確認します。
予想としては、プロトタイプのほうはインスタンスを取得するタイミングで2回コンストラクタを実行するログが出るはずです。シングルトンのほうは、1回何処かででるはず。
ということで実行!
ApplicationContextを作成
======================================
MyBean コンストラクタ
プロトタイプのBeanを2つ取得
MyBean コンストラクタ
MyBean コンストラクタ
処理を実行
MyBean#execute()実行
MyBean#execute()実行
======================================
シングルトンのBeanを2つ取得
処理を実行
MyBean#execute()実行
MyBean#execute()実行
ApplicationContextのインスタンス作成直後のタイミング(3行目)でMyBeanのインスタンスが1つ作られていることが確認できます。
これが、シングルトンのMyBeanのインスタンスが作成されるタイミングです。
その後プロトタイプが2つ作られているのがわかります。最後のシングルトンのインスタンスを取得している所ではインスタンスが作られていないことも確認できます。
ということでまとめ。
- scopeは、Springのコンテナがbeanのインスタンスをどの単位で管理するかを指定するもの
- scopeは、5つある。
- webアプリ以外ではprototypeとsingletonの2つが使える。
- singletonはコンテナが作成されたタイミングでインスタンスが作成されて、それが使いまわされる。
- prototypeは、beanが取得されるたびにインスタンスが作られる。
以上です。