山崎屋の技術メモ

IT業界で働く中でテクノロジーを愛するSIerのシステムエンジニア👨‍💻 | AndroidとWebアプリの二刀流🧙‍♂️ | コードの裏にあるストーリーを綴るブログ執筆者✍️ | 日々進化するデジタル世界で学び続ける探究者🚀 | #TechLover #CodeArtisan、気になること、メモしておきたいことを書いていきます。

Eclipse ではじめる初めての Spring4

Web アプリケーションフレームワークデファクトスタンダードといって良い spring について勉強していきたい。最近は
SpringBoot の記事がはやっているが、Spring の基本的なことを勉強したいときには SpringBoot はブラックボックスの箇所が多すぎて適さない。ここでは、SpringBoot を使用しないコンソールアプリを用いて学習したい。

各ソフトウェアのバージョンは以下のとおり。

・OS:Windows7 64bit

Java:1.8.0

Eclipse:4.6(neon

・spring:4.3.2

STS はインストール済み。STS のインストールは以下を参考にする。

qiita.com

Eclipse は英語版を使用しているため、メニューなどの説明は英語で記載している。日本語版を使っている人は脳内翻訳して解釈して欲しい。

プロジェクトの作成

パッケージエクスプローラで右クリック→[new]→[Other]を選択すると次の画面が表示される。

f:id:yyama1556:20160807123448p:plain

次のように[Spring]→[Spring Legacy Project]を選択する。

f:id:yyama1556:20160807123624p:plain

[new Spring Legacy Project]画面が表示されるのでプロジェクト名に[Sample]と入力し、[Templates]に[Simple Spring Maven]を選択して、[finish]ボタンクリック。

f:id:yyama1556:20160807123949p:plain

すると Sample というプロジェクトが作成される。フォルダ構成は次のようになっている。

f:id:yyama1556:20160807124620p:plain

pom.xml の修正

プロジェクト作成後の pom.xml の次の箇所を修正する。

Javaのバージョン: 1.6 → 1.8

・Springのバージョン: 3.2.3-RELEASE → 4.3.2.RELEASE

Dependency: spring-contextを残して他を全部削除

修正前の 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>Sample</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
  <properties>

		<!-- Generic properties -->
		<java.version>1.6</java.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

		<!-- Spring -->
		<spring-framework.version>3.2.3.RELEASE</spring-framework.version>

		<!-- Hibernate / JPA -->
		<hibernate.version>4.2.1.Final</hibernate.version>

		<!-- Logging -->
		<logback.version>1.0.13</logback.version>
		<slf4j.version>1.7.5</slf4j.version>

		<!-- Test -->
		<junit.version>4.11</junit.version>

	</properties>
	
	<dependencies>
		<!-- Spring and Transactions -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>

		<!-- Logging with SLF4J & LogBack -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${slf4j.version}</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>${logback.version}</version>
			<scope>runtime</scope>
		</dependency>

		<!-- Hibernate -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>${hibernate.version}</version>
		</dependency>

		
		<!-- Test Artifacts -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${spring-framework.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit.version}</version>
			<scope>test</scope>
		</dependency>

	</dependencies>	
</project>

修正後の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>Sample</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>

		<!-- Spring -->
		<spring-framework.version>4.3.2.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>

Main クラスの作成

[src/main/java]の下に[org.yyama]というパッケージを作成する。その下にmainメソッドを含むMainクラスを作成する。

Mainクラス

package org.yyama;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
	public static void main(String... args) {
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
		Main tMain = ctx.getBean(Main.class);
		tMain.proc();
		ctx.close();
	}

	public void proc() {
		System.out.println("procの中");
	}
}

この時点で実行すると、[applicationContext.xml]ファイルをまだ作成していないため、例外[BeanDefinitionStoreException]が発生する。

この時点で実行したときのコンソール

8 07, 2016 1:18:21 午後 org.springframework.context.support.AbstractApplicationContext prepareRefresh
情報: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1f17ae12: startup date [Sun Aug 07 13:18:21 JST 2016]; root of context hierarchy
8 07, 2016 1:18:21 午後 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
情報: Loading XML bean definitions from class path resource [applicationContext.xml]
Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [applicationContext.xml]; nested exception is java.io.FileNotFoundException: class path resource [applicationContext.xml] cannot be opened because it does not exist
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:341)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:174)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:209)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:180)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:243)
	at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:127)
	at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:93)
	at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:130)
	at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:537)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:451)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
	at org.yyama.Main.main(Main.java:7)
Caused by: java.io.FileNotFoundException: class path resource [applicationContext.xml] cannot be opened because it does not exist
	at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:157)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:328)
	... 13 more

applicationContext.xml の作成

[src/main/resources]の下に[applicationContext.xml]を作成する。

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"
	xsi:schemaLocation="
      http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean class="org.yyama.Main" />
</beans>

完成

これで簡単なサンプルは完了。実行すると期待とおり"procの中"というメッセージがコンソールに表示される。

8 07, 2016 1:42:51 午後 org.springframework.context.support.AbstractApplicationContext prepareRefresh
情報: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1f17ae12: startup date [Sun Aug 07 13:42:51 JST 2016]; root of context hierarchy
8 07, 2016 1:42:51 午後 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
情報: Loading XML bean definitions from class path resource [applicationContext.xml]
8 07, 2016 1:42:52 午後 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
情報: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@d041cf: defining beans [org.yyama.Main#0]; root of factory hierarchy
procの中
8 07, 2016 1:42:52 午後 org.springframework.context.support.AbstractApplicationContext doClose
情報: Closing org.springframework.context.support.ClassPathXmlApplicationContext@1f17ae12: startup date [Sun Aug 07 13:42:51 JST 2016]; root of context hierarchy
8 07, 2016 1:42:52 午後 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
情報: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@d041cf: defining beans [org.yyama.Main#0]; root of factory hierarchy

最後に

このように、Spring では Java のクラスをコンテナに登録し、必要に応じて登録したクラスのインスタンスを取得することが基本の動きになる。

今回は XML ファイルでクラスを指定してコンテナに登録した。これを XML コンフィグという。そのほか アノテーション を用いてコンテナにクラスを登録するアノテーションコンフィグ。また、Java のクラスを用いてコンテナにクラスを登録する Java コンフィグがある。

アノテーションコンフィグについては別途記事にした。
yyama1556.hateblo.jp


Java コンフィグは柔軟な設定が書ける分、大規模システムでの使用は難しいかも知れない。(柔軟すぎてあちこちで、独自の設定方法で書かれやすい。)ただ、一人で作業する分には綴りのミスなどが起きにくい分(コンパイラーがミスを教えてくれる。)効率よく開発できる。


Spring 関連記事へのリンク集つくりました。