はじめに
こんにちは、Gakken LEAP のエンジニアの okamotoです。
普段の業務で使用しているSpring Bootについて、使ってはいるものの仕様や仕組みについて理解ができていない部分が多いと感じたため、基本から学んでみました。
今回はその一歩目として学んだものを備忘録として本記事にのこします。
Spring Bootの登場
Springフレームワークの中の一つにSpring MVCというMVCモデルに基づいたフレームワークがあり、
それだけでは他のフレームワークを色々組み合わせなければならず、使いづらい部分があった。
(Spring Rooという各種コードの自動生成機能ライブラリで補完することである程度は楽になっていた)
そこで登場したSpring BootはSpring MVCの完成系とされており、上記の二つ+αの組み合わせを完全に上回った利便性がある。
Spring Bootの利便性とは
とにかく楽である。
どう楽なのかというと、
他のフレームワークを色々組み合わせなければならず
↑の部分を設定ファイルにスターターライブラリをちょっと書くだけで全部自動にやってくれるようになるからだ。
ここまでの話はただ開発するだけであれば特に意識する必要はないのかもしれないが、
覚えておいていざその話題になった時なんとなく参加できると、なんだかエンジニアっぽい雰囲気が醸し出せるのかもしれない。
Spring Bootではビルド時にBeanが作成される
Beanとはなにか?
簡単に言えばインスタンスである。(明確には異なるが大体はその認識であまり問題はないと思われる)
SpringではDIコンテナというものがあり、ビルドされた時に自動的にBean(インスタンス)を作り、
DIコンテナに格納してくれる。
つまりDIコンテナは生成されたインスタンスを入れておく容れ物ということらしい。
これも開発をするときに意識しなくても良い気がするが、理解はしておくと何か発展的なお勉強をした際の助けになるかもしれない。
ビルド時にクラスのBeanを作成してもらう方法としてはいくつか種類があるが、基本的には@⚪︎⚪︎の形で記述される、アノテーションというものを使用することでBean作成の対象とすることができる。
今回は@Componentあたりを使う方法を前提とする。
DI:依存性の注入とは
Dependency Injectionの略
Springにおける基本思想であり、常にこれを意識した実装を行うのがSpringによる開発の基本である。
※ここでの「依存性」とはあるクラス(=使う側)が他のクラス(=使われる側)を利用している状態
使う側のクラスA、使われる側のクラスBが存在する際に、クラスBから作成されたBeanをクラスAのフィールド変数に代入するということらしい。
便利な点はいくつかあるらしいがいったんは概念だけの話としたいので割愛。
アノテーション
@Component
クラスからBeanを作成したい場合に記述するアノテーション
(ただしその中でも最もシンプルなもの)
例えば、「Hoge」クラスにこれを書いておけばビルド時に「hoge」という名称のBeanが生成される(頭文字が小文字になる)
ただし上記はデフォルトでBean生成を行った場合であり、名称の指定も可能。
@Component("Fuga")と記述した場合、「hoge」というBeanは作成されず、「Fuga」というBeanが作成される。(これにより頭文字を大文字にすることも可能)
@Autowired
生成したBeanを呼び出す場合に記述するアノテーション
例えば、呼び出し元クラスで@Autowiredを記述してHoge型のフィールド変数を定義することで、
その変数にHogeのBeanが注入(Injection)される。
@Componentの仲間
※基本的には一緒なのでお作法としてどこで何を使うべきかを把握しておく
@Controller
クライアントとのデータ入出力を制御する(画面からHTTPリクエストを受け付ける)クラスに付与する
@Service
ビジネスロジックの処理を行うクラスに付与する
@Repository
データベースとのやり取りを行うクラスに付与する
クラス依存とインターフェース依存
クラス依存
クラス依存は、クラスAがクラスBを直接呼び出している状態
この状態でクラスBに修正が入りクラスの修正(クラスB→クラスC)やメソッドの修正(メソッドB→メソッドC)が入った際、呼び出す側のクラスAでクラスBの記述を行われている箇所も修正する必要がある。
このような構造は依存度が高く、柔軟性に欠ける。
インターフェース依存
インターフェース依存はクラス依存とは異なり、クラスAからインターフェースBを呼び出している状態
(インターフェースBをimplementしているクラスBが存在する)
この状態でクラスBに修正が入りクラスの修正(クラスB→クラスC)やメソッドの修正(メソッドB→メソッドC)が入った際、同じくインターフェースBをimplementしたクラスCを作成することで、呼び出す側のクラスAに修正を行う必要がなくなり、「低依存」な状態にできるというメリットがある。
Spring Bootでのインターフェース依存とDIの活用
Spring Bootでは、このインターフェース依存をさらに強化するために@Autowiredを利用して依存性の注入(DI)が可能。
@Autowiredを使うことで、Springがインターフェースを実装している適切なクラス(インスタンスやBean)を自動的に注入してくれる。
これにより、クラスAは具体的なクラスBやクラスCに直接依存することなく、インターフェースBを通じてSpringのDIコンテナにより最適な実装を受け取ることができる。この仕組みは、柔軟で拡張可能なアプリケーション設計を支援し、Spring Bootの強力な機能の一つと言える。
おわりに
Gakken LEAP では教育をアップデートしていきたいエンジニアを募集しています。
参考
https://euske.github.io/slides/spring202301/index.html
https://qiita.com/ist-a-ku/items/1d278619f241f4800bb2
https://qiita.com/shuncask/items/baf064182ce530ec26cd
https://qiita.com/ist-a-ku/items/c20d67140402634cd5db
https://www.issoh.co.jp/tech/details/2639/