SpringFrameworkの海に飛び込んでみた
IT技術
はじめに
はじめまして!7月に入社した武田と申します。
10月から参入する案件でSprignBootを使うということで、現在キャッチアップをしています。その中で度々「DI」という言葉が出てきたので、その周辺概念をざっくり整理してみました。
DI(Dependency Injection)とは
直訳すると「依存性の注入」で、これはクラス間の依存関係を付与するアクションになります。
依存関係を持たせると聞いて、「クラスAの中でクラスBをインスタンス化させるだけのことでは?」と思っていました。
1public class A {
2 private B b;
3 // コンストラクタでクラスBのインスタンスを生成
4 public A() {
5 b = new B();
6 }
7}
このようにクラスAがクラスBを直接参照するようにしてしまうと、クラスBが具象クラスであること等の制約が生またりと、クラスBを修正した際にクラスAも修正が必要になる可能性が生まれます。(密結合になりがち)
そこで、「依存関係の制御を、開発者(の作成したクラス)からSpringFramework側に移してしまおう」というのがDIのようです。
具体的には、上の例ですと、クラスAとクラスBの間に「Spring IoCコンテナ」が仲介します。
イメージ
このようにSpring IoCが間にいるおかげで、クラスAはクラスBのインスタンス生成方法を知る必要がなくなり、疎結合になりました。
制御の反転(IoC)
従来制御していた側が制御される側に回るということで、DIはこの概念の具体的なものに当たるようです。
コンピュータプログラミングの用語で制御の反転(Inversion of Control、IoC )とは、なんらかの種類のプログラムにおいて、プロシージャを「呼び出す側」と「呼び出される側」が、従来のプログラムとは逆になるようにする
DIは、オブジェクト(の依存関係)の制御が、開発者が書いたコードからSpringというフレームワーク側に移す行為という感じでしょうか。
そのためすごく乱暴に言ってしまえば、ここではIoC≒DIというイメージで問題ないのかなと思います。
Spring IoCコンテナとBean
DIを行うためにはDIしたいクラスを登録する必要があります。 Spring IoCコンテナで管理するクラスをBeanという単位で扱います。
Spring IoCコンテナはBeanをインスタンス化し、依存性注入を行います。
また、どのBean同士がどんな関係性を持つのかは「設定メタデータ」を参照します。
この設定メタデータは、「XML」、「Javaアノテーション」、「Javaコード」で表現が可能となっています。
設定例
XMLベースの設定
1<code class="language-java"><?xml version="1.0" encoding="UTF-8"?>
2<beans xmlns="<http://www.springframework.org/schema/beans>"
3 xmlns:xsi="<http://www.w3.org/2001/XMLSchema-instance>"
4 xsi:schemaLocation="<http://www.springframework.org/schema/beans>
5 <https://www.springframework.org/schema/beans/spring-beans.xsd>">
6
7 <!-- services -->
8
9 <bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
10 <property name="accountDao" ref="accountDao"/>
11 <property name="itemDao" ref="itemDao"/>
12 <!-- additional collaborators and configuration for this bean go here -->
13 </bean>
14
15 <!-- more bean definitions for services go here -->
16
17</beans></code>
Javaベース/アノテーションベースの設定
1@Configuration
2public class AppConfig {
3
4 @Bean
5 public ClientService clientService1() {
6 ClientServiceImpl clientService = new ClientServiceImpl();
7 clientService.setClientDao(clientDao());
8 return clientService;
9 }
10
11 @Bean
12 public ClientService clientService2() {
13 ClientServiceImpl clientService = new ClientServiceImpl();
14 clientService.setClientDao(clientDao());
15 return clientService;
16 }
17
18 @Bean
19 public ClientDao clientDao() {
20 return new ClientDaoImpl();
21 }
22}
イメージ
SpringBoot
SpringBootはSpringFrameworkを手軽に始められるようにしたもので、上述のXMLによる設定や、「@」から始まる「アノテーション」を使った設定用クラスを作成しなくてもSpringFrameworkの機能を使えるようになります。
上述のBean定義(どのクラスをBeanとしてIoCコンテナに登録するか)についてですが、mainメソッドのあるクラスに@SpringBootApplicationアノテーションをつけることで、登録をほぼ自動化できてしまいます。
例
1package payroll;
2
3import org.springframework.boot.SpringApplication;
4import org.springframework.boot.autoconfigure.SpringBootApplication;
5
6/*
7 * メインクラス
8 */
9@SpringBootApplication
10public class PayrollApplication {
11 /**
12 * プログラム実行の起点となるメソッド
13 * @param args
14 */
15 public static void main(String... args) {
16 SpringApplication.run(PayrollApplication.class, args);
17 }
18}
@SpringBootApplicationは以下のアノテーションを内包しています。
- @EnableAutoConfiguration: Springアプリケーションの自動設定を行う。
- @ComponentScan:@Componentアノテーション(またはこれを含む、@Controller,@Service,@Repositoryアノテーション)が付いているクラスを読み込む
- @Configuration: Spring IoCに追加の Bean を登録する。
つまり、このアノテーションを付けるだけで上述の設定をほぼ自動で行ってくれる形になります。
おわり
初めてSpringFrameworkを触るということで、「DI」を軸に基本的な概念や用語についてドキュメントを読んで学んでみました。
チュートリアルで作ったソースコードを改めて見返すと、理解できる部分が増えていたので嬉しかったです。
最後に、今回学習に使用したドキュメントを以下にまとめて終わりにしようと思います。ありがとうございました!
【SpringFramework概要】
Spring Framework の概要 - リファレンスドキュメント
【コア概念】
Spring Framework コアテクノロジー - リファレンス
【SpringBootの使用】
Spring Boot での開発 - リファレンスドキュメント
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ
2022年7月に入社しました。開発未経験で未知の領域だらけですが、楽しく学びつつ、早く戦力になれるようにがんばります!