はじめに
Javaを学ぶにあたり、研修でも使用されていることが多い「Spring Boot」。筆者はITエンジニア歴5年で4つの現場を経験してきましたが、研修以降は触れることがなかったため改めてSpring Bootについて思い出しながらまとめたいと思います。
1. Spring Bootの概要
Spring Bootとは
「Spring Framework」を基盤として作られたJavaのオープンソースWebフレームワークです。
Spring Frameworkのリリースが2004年で、Spring Bootのリリースは2014年と10年後に登場しました。
Spring Bootが作られた背景としては設定ファイル(XML)の内容、ライブラリ取得、Tomcatの設定を自分で準備する必要があるため、特に初心者にとっては、設定の段階でハードルが高くなりがちでした。Spring Bootではこれらをアプリケーション開発で想定される「おまかせ」設定で用意し、学習コストを下げるのが目的とされています。
主な特徴
・設定ファイルの準備が不要
Spring FrameworkではWeb.xmlを設定する必要があるが、Spring Bootでは不要です。
・組み込みサーバ
標準機能としてTomcatやJettyのWebコンテナが組み込まれており、これを利用することができます。
・WebコンテナをJARファイルに内包できる
上記に関連して、Webコンテナ(Tomcatなど)はJARファイルに組み込まれており、サーバー側へセットアップが不要です。
2.利用シーン
Spring Bootでは主に小~中規模向けの開発に使用されます。依存関係の管理と自動設定による開発コストの抑制を目的としての導入が多い印象です。
開発事例ではNetflix、LINEヤフー㈱では出前館、ZOZOTOWNをはじめ多くの製品でSpring Bootでの開発を行っています。
3. 利点
Spring Bootの大きな2つの利点としてDI(依存性注入)とAOP(アスペクト指向プログラミング)があります。今回はその中でもDIについて説明し、AOPについては次回の記事で詳しく解説したいと思います。
DI(依存性注入)とは?
DI(依存性注入)とは、簡単に言うと「外部からオブジェクトを注入する仕組み」です。
ただ単語だけでは理解が難しいため、下記の例えを参考にしてみてください。
例えばお客様がレストランに入ると、着席と同時にウェイターが自動的に水を持ってきてくれます。この時、お客様は自分で水を用意したり頼んだりせず、ウェイターが必要なもの(水)を自分に提供してくれます。
この例を以下のように置き換えると、DIの仕組みが理解しやすくなります。
ウェイター:Spring Boot
お客様 :クラス
水 :依存性(オブジェクト)
ウェイターがいない場合、水を飲みたければセルフサービスで用意する必要があるが、ウェイターがいることによってこの手間を省くことができるというわけです。
DIをコードにした例
次にこの概念をコードで表現してみます。以下のコードでは、Waterクラス、Waiterクラス、Customerクラスを使ってDIの仕組みをシンプルに示しています。
・Waterクラス: 水を提供する役割のクラスです。
・Waiterクラス: 水を提供するウェイターの役割を担うクラスです。Waterクラスに依存しており、その依存関係はSpring BootのDIにより自動的に注入されます。
・Customerクラス: 客の役割を担うクラスです。Waiterクラスに依存しており、これもDIにより注入されます。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
// 水(依存性)を提供するクラス
@Component
public class Water {
public String serve() {
return "水をお持ちしました。";
}
}
// ウェイター(依存性注入者)のクラス
@Component
public class Waiter {
private final Water water;
// DIによってWaterオブジェクトが自動的に注入される
@Autowired
public Waiter(Water water) {
this.water = water;
}
public void serveWater() {
System.out.println(water.serve());
}
}
// お客様のクラス
@Component
public class Customer {
private final Waiter waiter;
// DIによってWaiterオブジェクトが自動的に注入される
@Autowired
public Customer(Waiter waiter) {
this.waiter = waiter;
}
public void sitDownAndOrder() {
System.out.println("お客様が座りました。");
waiter.serveWater(); // ウェイターが水を提供
}
}
// Spring Boot アプリケーションクラス
@SpringBootApplication
public class RestaurantApplication {
public static void main(String[] args) {
// Spring Boot が DI を通じて依存関係を解決する
ApplicationContext context = SpringApplication.run(RestaurantApplication.class, args);
// お客様が座って水を注文
Customer customer = context.getBean(Customer.class);
customer.sitDownAndOrder(); // ウェイターが水を提供する
// 実行結果
// お客様が座りました。
// 水をお持ちしました。
}
}
このコードで注目すべきポイントは、以下の通りです:
1.@Componentアノテーション
・@Componentアノテーションは、このクラスをSpringコンテナの管理対象としてマークする役割を果たします。これにより、Spring Bootが自動的にインスタンスを生成し、必要なクラスに依存性を注入します。
2.@Autowiredアノテーション
・@Autowiredは、コンストラクタに対して付けられ、Spring Bootが必要な依存関係(WaterクラスやWaiterクラス)を自動的に注入することを意味します。これにより、開発者が明示的にインスタンス化する必要がなくなります。
3.依存性の注入
・WaterクラスはWaiterクラスに、WaiterクラスはCustomerクラスに依存しています。これらの依存関係はSpring BootのDIによって管理され、アプリケーションが実行される際に自動的に解決されます。
DIを使うメリット
DIを使用することで得られるメリットは以下の3点です。
テスト作業の向上
DIを使うことで実際に依存しているクラスがまだ完成していない場合も、モックやスタブといった代替クラスでテストを進めることが可能です。
保守性の向上
毎回インスタンス化を行う必要がなく、コードの可読性が向上し、
メンテナンスの際もDIコンテナの設定を変更するだけでよいため修正が容易です。
コンポーネントの再利用性
上記に関連しますが、依存性注入により保守性が高まったことで他のクラスやコンテキストでコンポーネントを再利用しやすい。
4.まとめ
以上が具体例を用いたDIの説明となります。日常生活の身近な例を参考にしてSpring Bootの取っ掛かりとして読んでもらえれば幸いです。