タイトルに書いたとおりだが、Spring を使用する上でこれを常に頭に入れておかないと、とんでもないバグを仕込んでしまう。
実験してみる
Spring のバージョンは 4.3.7 を使用しているが、他のバージョンでも、これに関しての仕様は同じ。
フォルダ構成。
pom.xml。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.springframework.samples</groupId> <artifactId>ProjectX</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <!-- Generic properties --> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <maven.compiler.target>${java.version}</maven.compiler.target> <maven.compiler.source>${java.version}</maven.compiler.source> <!-- Spring --> <spring-framework.version>4.3.7.RELEASE</spring-framework.version> </properties> <dependencies> <!-- Spring and Transactions --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring-framework.version}</version> </dependency> </dependencies> </project>
applicationContext.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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="org.yyama.bean" /> </beans>
ClassA は空っぽ。 @Component だけ付けている。
package org.yyama.bean; import org.springframework.stereotype.Component; @Component public class ClassA { }
Main クラス。
package org.yyama.main; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.yyama.bean.ClassA; public class Main { public static void main(String... args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); ClassA class1 = context.getBean(ClassA.class); ClassA class2 = context.getBean(ClassA.class); if (class1 == class2) { System.out.println("2つのインスタンスは同じものです。"); } else { System.out.println("2つのインスタンスは異なるものです。"); } context.close(); } }
ClassA のインスタンスを 2 回取得し、それが同じものなのか別のものなのか判定している。
実行するとこうなる。
2つのインスタンスは同じものです。
このように、Spring のコンテナは同じインスタンスを複数回渡してくる。
例えば、インスタンス変数にユーザーごとの状態を保持しておいたりすると、あるユーザへの変更が全ユーザに反映されてしまう。単体テストでは発見しにくいバグを作り込んでしまうので注意が必要だ。
呼び出すたびに別のインスタンスが欲しい場合
ClassA に Scope アノテーションを付与し、パラメータに "prototype" を指定する。
package org.yyama.bean; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @Component @Scope("prototype") public class ClassA { }
これで main メソッドを実行すると、結果はこうなった。
2つのインスタンスは異なるものです。
"prototype"のほかに"singleton"があり、これがデフォルトで適用される。Scope アノテーションを省略するとシングルトンになる。
Spring の web アプリケーションでは、"request"や"session"も使用できる。"global-session"というのもあるらしいが、今のところ興味ない。
まとめ
基本的なことなので、これを知らずに開発している人がいたら教えてあげましょう。これ大事です。
↓↓↓ Spring Framework 関連の記事をまとめました。
yyama1556.hateblo.jp
Spring徹底入門 Spring FrameworkによるJavaアプリケーション開発
- 作者: 株式会社NTTデータ
- 出版社/メーカー: 翔泳社
- 発売日: 2016/07/20
- メディア: Kindle版
- この商品を含むブログ (1件) を見る
「プロになるためのWeb技術入門」 ――なぜ、あなたはWebシステムを開発できないのか
- 作者: 小森裕介
- 出版社/メーカー: 技術評論社
- 発売日: 2010/04/10
- メディア: 大型本
- 購入: 57人 クリック: 1,242回
- この商品を含むブログ (35件) を見る
[改訂新版]Spring入門 ――Javaフレームワーク・より良い設計とアーキテクチャ
- 作者: 長谷川裕一,大野渉,土岐孝平
- 出版社/メーカー: 技術評論社
- 発売日: 2016/06/14
- メディア: Kindle版
- この商品を含むブログを見る