SpringのIoC、Spring Beanの例のチュートリアル
「Spring IoCのサンプルチュートリアルへようこそ。Spring Frameworkは、制御の反転の原則に基づいて構築されています。依存性注入は、アプリケーションにIoCを実装するための手法です。」
Spring IoC
スプリングIoC
今日はSpring IoCコンテナを見ていきます。また、Spring Beanについても確認します。以下は、Spring IoCチュートリアルの異なるセクションへのクイックナビゲーションのための目次です。
-
- Spring IoC(SpringのInversion of Control)
-
- Spring Bean(SpringのBean)
-
- Spring Bean Scopes(SpringのBeanのスコープ)
-
- Spring Bean Configuration(SpringのBeanの設定)
-
- Spring IoC and Spring Bean Example(SpringのIoCとBeanの例)
XMLベースのSpring Beanの設定
アノテーションベースのSpring Beanの設定
JavaベースのSpring Beanの設定
スプリングのIoCコンテナ
Spring IoCは、オブジェクト間の疎結合を実現するためのメカニズムです。オブジェクトの依存関係を疎結合化し、ランタイム時にオブジェクトの依存関係を他のアセンブラーオブジェクトによって注入します。Spring IoCコンテナは、依存関係をオブジェクトに注入し、使用可能な状態にするプログラムです。Springの依存性注入を使用して、IoCをアプリケーションに実装する方法をすでに見てきました。Spring IoCコンテナのクラスは、org.springframework.beansとorg.springframework.contextパッケージの一部です。Spring IoCコンテナは、オブジェクトの依存関係を解除するためのさまざまな方法を提供しています。BeanFactoryは、Spring IoCコンテナのルートインターフェイスです。ApplicationContextは、BeanFactoryインターフェイスの子インターフェイスで、Spring AOPの機能、i18nなどを提供します。ApplicationContextのいくつかの有用な子インターフェイスには、ConfigurableApplicationContextとWebApplicationContextがあります。Springフレームワークは、Springのコンテキストを取得し、Spring Beanを取得するために使用できるさまざまな有用なApplicationContextの実装クラスを提供しています。使用できるいくつかのApplicationContextの実装には、次のものがあります。
- AnnotationConfigApplicationContext: If we are using Spring in standalone java applications and using annotations for Configuration, then we can use this to initialize the container and get the bean objects.
- ClassPathXmlApplicationContext: If we have spring bean configuration xml file in standalone application, then we can use this class to load the file and get the container object.
- FileSystemXmlApplicationContext: This is similar to ClassPathXmlApplicationContext except that the xml configuration file can be loaded from anywhere in the file system.
- AnnotationConfigWebApplicationContext and XmlWebApplicationContext for web applications.
通常、もしSpring MVCアプリケーションで作業していて、アプリケーションがSpring Frameworkを使用するように設定されている場合、アプリケーションが起動した時にSpring IoCコンテナが初期化され、また、特定のbeanが要求された時に依存関係が自動的に注入されます。しかし、スタンドアロンアプリケーションにおいては、アプリケーションのどこかでコンテナを初期化し、その後、Springのbeanを取得するために使用する必要があります。
スプリングビーン
Spring Beanとは特別なものではありません。Springコンテナを介して初期化するSpringフレームワークのオブジェクトは、すべてSpring Beanと呼ばれます。通常のJava POJOクラスも、設定メタデータ情報を提供してコンテナを介して初期化されるように構成されれば、Spring Beanになることができます。
春のビーンスコープ
Spring Beansには5つのスコープが定義されています。
-
- singleton(シングルトン)- 各コンテナに対して一つのbeanインスタンスが作成されます。これはSpringのbeanのデフォルトのスコープです。このスコープを使用する場合、beanに共有のインスタンス変数がないことを確認してください。そうでないと、データの不整合の問題が発生する可能性があります。
prototype(プロトタイプ)- beanが要求されるたびに新しいインスタンスが作成されます。
request(リクエスト)- これはprototypeスコープと同じですが、ウェブアプリケーションに使用するためのものです。HTTPリクエストごとに新しいbeanインスタンスが作成されます。
session(セッション)- コンテナによって、各HTTPセッションに対して新しいbeanが作成されます。
global-session(グローバルセッション)- ポートレットアプリケーション用のグローバルセッションbeanを作成するために使用されます。
Spring Frameworkは拡張性があり、自分自身でもスコープを作成することができます。しかし、ほとんどの場合、フレームワークで提供されているスコープで十分です。
スプリングビーンの設定
Spring Frameworkは、アプリケーションで使用するために、ビーンを設定するための三つの方法を提供しています。
-
- アノテーションに基づく設定 – @Serviceや@Componentのアノテーションを使用します。スコープの詳細は@Scopeアノテーションで指定できます。
-
- XMLに基づく設定 – Spring Configuration XMLファイルを作成して、ビーンを構成します。Spring MVCフレームワークを使用している場合は、web.xmlファイルにいくつかの基本的なコードを書くことで、XMLベースの設定を自動的にロードすることができます。
- Javaに基づく設定 – Spring 3.0から、Javaプログラムを使用してSpringのビーンを構成することができます。Javaに基づく構成に使用されるいくつかの重要なアノテーションは@Configuration、@ComponentScan、@Beanです。
Spring IoCとSpring Beanの例のプロジェクト
簡単なSpringプロジェクトで、Spring IoCコンテナとSpring Beanの構成の異なる側面を見てみましょう。私の例では、Spring Tool SuiteでSpring MVCプロジェクトを作成しています。もしSpring Tool SuiteとSpring MVCが初めての場合は、Spring MVCチュートリアル with Spring Tool Suiteをお読みください。最終的なプロジェクトの構造は以下の画像のようになります。Spring IoCおよびSpring Beanプロジェクトの異なるコンポーネントを一つずつ見ていきましょう。
XMLベースのSpring Beanの設定
MyBeanはシンプルなJavaのPOJOクラスです。
package com.scdev.spring.beans;
public class MyBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
春の設定XMLファイル
「servlet-context.xml」のコードの内容を日本語で言い換えると、「サーブレットコンテキスト.xml」ファイルのコードとなります。
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="https://www.springframework.org/schema/mvc"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="https://www.springframework.org/schema/beans"
xmlns:context="https://www.springframework.org/schema/context"
xsi:schemaLocation="https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.scdev.spring" />
<beans:bean name="myBean" class="com.scdev.spring.beans.MyBean" scope="singleton" ></beans:bean>
</beans:beans>
MyBeanはsingletonとしてスコープを指定してbean要素を使用して構成されていることに注意してください。
アノテーションを基にしたSpring Beanの設定
package com.scdev.spring.beans;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.web.context.WebApplicationContext;
@Service
@Scope(WebApplicationContext.SCOPE_REQUEST)
public class MyAnnotatedBean {
private int empId;
public int getEmpId() {
return empId;
}
public void setEmpId(int empId) {
this.empId = empId;
}
}
MyAnnotatedBeanは@Serviceを使用して構成され、スコープはRequestに設定されています。
Spring IoC(Inversion of Control)のコントローラークラス
HomeControllerクラスは、アプリケーションのホームページのHTTPリクエストを処理します。このコントローラークラスには、WebApplicationContextコンテナを介して私たちのSpring beansをインジェクションします。
package com.scdev.spring.controller;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.scdev.spring.beans.MyAnnotatedBean;
import com.scdev.spring.beans.MyBean;
@Controller
@Scope("request")
public class HomeController {
private MyBean myBean;
private MyAnnotatedBean myAnnotatedBean;
@Autowired
public void setMyBean(MyBean myBean) {
this.myBean = myBean;
}
@Autowired
public void setMyAnnotatedBean(MyAnnotatedBean obj) {
this.myAnnotatedBean = obj;
}
/**
* Simply selects the home view to render by returning its name.
*/
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
System.out.println("MyBean hashcode="+myBean.hashCode());
System.out.println("MyAnnotatedBean hashcode="+myAnnotatedBean.hashCode());
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
return "home";
}
}
デプロイメント記述子
私たちはSpringフレームワークのアプリケーションを設定する必要があります。そのために、設定メタデータが読み込まれ、コンテキストが初期化されます。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="https://java.sun.com/xml/ns/javaee"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
ほぼすべての構成情報は、STSツールによって自動的に生成されるひな型コードです。
Spring IoCビーンの例アプリケーションを実行する。
今度ウェブアプリケーションを起動すると、ホームページが読み込まれ、ページを複数回リフレッシュすると、コンソールに以下のログが表示されます。
MyBean hashcode=118267258
MyAnnotatedBean hashcode=1703899856
MyBean hashcode=118267258
MyAnnotatedBean hashcode=1115599742
MyBean hashcode=118267258
MyAnnotatedBean hashcode=516457106
MyBeanはシングルトンとして設定されているため、コンテナは常に同じインスタンスを返し、ハッシュコードも常に同じです。同様に、各リクエストごとに異なるハッシュコードでMyAnnotatedBeanの新しいインスタンスが作成されます。
SpringのBean設定はJavaをベースとしています。
単体アプリケーションでは、アノテーションベースとXMLベースの設定の両方を使用することができます。唯一の要件は、プログラム内のどこかでコンテキストを初期化することです。
package com.scdev.spring.main;
import java.util.Date;
public class MyService {
public void log(String msg){
System.out.println(new Date()+"::"+msg);
}
}
MyServiceはいくつかのメソッドを持つシンプルなJavaクラスです。
package com.scdev.spring.main;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(value="com.scdev.spring.main")
public class MyConfiguration {
@Bean
public MyService getService(){
return new MyService();
}
}
Springコンテナを初期化するために使用されるアノテーションベースの設定クラス。
package com.scdev.spring.main;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MyMainClass {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
MyConfiguration.class);
MyService service = ctx.getBean(MyService.class);
service.log("Hi");
MyService newService = ctx.getBean(MyService.class);
System.out.println("service hashcode="+service.hashCode());
System.out.println("newService hashcode="+newService.hashCode());
ctx.close();
}
}
以下の内容を日本語で自然に言い換える:
AnnotationConfigApplicationContextコンテキストを初期化し、getBean()メソッドを使ってMyServiceのインスタンスを取得する簡単なテストプログラムです。MyServiceにはスコープが定義されていないため、シングルトンであるはずであり、そのためインスタンスのハッシュコードは同じであるはずです。上記のアプリケーションを実行すると、以下のコンソール出力が表示され、私たちの理解が確認されます。
Sat Dec 28 22:49:18 PST 2013::Hi
service hashcode=678984726
newService hashcode=678984726
XMLベースの設定をお探しであれば、まずSpring XML設定ファイルを作成し、次に以下のコードスニペットでコンテキストを初期化してください。
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"applicationContext.xml");
MyService app = context.getBean(MyService.class);
これで、Spring IoCの例チュートリアル、Spring Beanのスコープと設定の詳細は以上です。Spring IoCとSpring Beanの例プロジェクトは以下のリンクからダウンロードして、理解を深めるために実際に試してみてください。
スプリングビーンズプロジェクトをダウンロードしてください。 (Supuringu Bīnzu Purojekuto o daunrōdo shite kudasai.)
参照文献:Spring.IOのIOCページ