Springについて勉強したことまとめる#2-1 (事前知識:DI,AOP,Bean,ApplicationContext)

こんにちは！
23卒新卒エンジニアのkamaです！
前回springの概要について、技術書[Spring徹底入門](https://www.shoeisha.co.jp/book/detail/9784798142470 "公式リンク")をベースに記事にしました。

https://qiita.com/kama1021/items/30230ee4ab4983c1a5f3

今回はその続きになります！
が、事前知識があまりにも多く、まだまだ本文には入れそうにないので、チャプター2を何部かに分けて、記事を書いていこうと思います。
今回は事前知識編と題して、`DI`、`AOP`、`Bean`、`ApplicationContext`について勉強しながら解説していこうと思います。

## DI(依存性注入)
Dependency Injection
DIはオブジェクト指向プログラミングをしていれば必然的に覚えることになるので、ここでしっかり勉強しちゃいましょう！

オブジェクト指向を学んだことがある人なら1度ぐらいは聞いたことがあるであろうDI。
依存性という抽象的な単語は聞いただけでは理解できない人も多いのではないでしょうか？
かくいう私も以前SOLID原則について勉強した際に、依存性逆転の法則だけ自分なりの解釈を持てずに終わってしまったという過去があるので、この場でしっかり理解しようと思います。

いきなり依存性の注入といわれても意味が分からないと思うので、依存性を理解して、動注入するのかという流れで理解しましょう。

#### 依存性とは
**あるオブジェクトやクラス、モジュールが他のオブジェクトやクラス、モジュールの存在や機能に頼っている状態。**
よくある車にたとえた話だと、`Car`クラスはエンジン機能を実装する際に`Engine`クラスのインスタンスを自分の中に生成しますね。
ですが、`Car`クラスで`ElectricEngine`を使いたいとなった時、`Car`クラスそのものを弄ることになってしまいます。
これが1回ならいいですけど、何回もエンジンの種類が変わってしまったら、非常にめんどくさいですね。

#### 注入とは
注入というのは日常的にたま～に聞くので、なんとなく理解はできるでしょう。
おそらくイメージしているまんまのことをプログラムでもすることになります。
先ほどの依存性を解決するために、`Car`クラスは`Engine`クラスそのものではなく、`IEngine`というインターフェースを実装します。
そして`Car`クラスのインスタンスを生成する際に、そのクラスから`IEngine`インターフェースを実装した`Engine`クラスを注入してもらう。
という手段を踏むことで、`Car`クラスは実際に使用するエンジンを気にすることなく実装することができるようになります。

**これが依存性の注入(DI)です**

Spring Frameworkでは、このDIを自動的に管理することができる**DIコンテナ**というツールが搭載されており、実際にはそこまで難しく考えなくても実装できるようになっている。

### AOP(アスペクト指向プログラミング)
Aspect Oriented Programming
**横断的関心をモジュール化することを目指すプログラミングパラダイム**
という説明がありました。

はい。ここで意味が分からないものが2つ出てきました。
**横断的関心**と**プログラミングパラダイム**ですね。
まずは、技術的な部分からは少し離れている、**プログラミングパラダイム**について話します。

#### プログラミングパラダイム
プログラミングをするうえで、どのように問題を解決するべきか、という``指針``や``考え方``の発生を指すことが多い。
あくまでも**新しい機能やツールの登場によって引き起こされるものではなく、プログラマ自身の考え方や物のとらえ方によって起きる**というのが面白いところ。
有名なものでは、
**手続き型プログラミング** → **オブジェクト指向プログラミング** → **関数型プログラミング** 
のような形で、その時代のプログラマが既存の考え方に違和感を持ち、それを解決するために制約やルールを作り出したときに生まれる事が多い。

これに関してわかりやすく解説しているYoutubeの動画があるので、リンクを置いておきます。(結構再生時間が長いですが、ラジオとして聞けて、初学者でもわかりやすくて面白いのでお勧めです！)

https://www.youtube.com/playlist?list=PL0GEQcnC7e3btHVKYY6rl912CfqeHvuOH

#### 横断的関心
この横断的関心という言葉も、わかりにくいので、横断と感心に分けましょう。

**横断**
というのは、1つの機能や責任がアプリケーションのクラスやモジュール複数個所にまたがって存在している状態のことを指します。
ログ出力や認証といったような、クラスの主要な仕事ではないが、色々なところで必要になるからそれぞれのスクリプトに点在しているコードが主に横断している状態であることが多いく、そういった状況を「横断的」と呼ぶ。

**関心**
プログラムやシステムが扱うべき特定の機能や責任のこと。
ソフトウェア開発における、「ビジネスロジック」「データアクセス」「ログ出力」「認証」などの各ロジックそのものがそれぞれの``関心``を形成する。

ここまで見ると横断的関心がよくわかりますね。
横断的関心とは、そのままの意味で、**横断的になってしまっている関心**のことなんですね。


#### 話を戻して
つまるところ、アスペクト指向プログラミングとは、
**複数個所にまたがっているロジックをモジュール化してまとめようという考え方の指針**なんですね



DI、AOPについてはわかってもらえたでしょうか？
私は、以前だと結構難しくてあきらめちゃった依存性周りのことを再度勉強してみたら理解できたので、よかったです！



## Bean
これまでDIとAOPについての説明を長々としてきましたが、じゃあ実際SpringFrameworkではどう使われているんだっていう話ですよね。
まずはDIのお話です。

SpringFrameworkでは、**アプリケーションコンテキスト**という機能によってDIコンテナが実装されています。

この**アプリケーションコンテキスト**について説明する前に、説明しないといけないものが1つあり、それが**Bean**というものです。
これは、難しく考えすぎる必要はなく、Javaで作成したオブジェクトをアプリケーションコンテキストから一元的に管理できるようにしたもの、という認識で問題ないと思います。
Beanの宣言にはアノテーションというものを付ける必要があります。
```java:Beanクラスの宣言
@Component
public class MyClass{
    //クラスのコード
}
```
このように、Beanオブジェクトとしたいものの前に`@機能名`を付けるだけです！
上記の例ではクラスの宣言ですが、他にも、メソッド、インターフェース、ファクトリメソッドをBeanオブジェクトとして宣言することができます。

アノテーションには、他にもいくつも種類があります。

| 機能名     |     宣言方法 | 
|:-----------|:------------|
|`@Component`|一般的なBeanクラスを示す| 
|`@Service`  |ビジネスロジックなどの、プロジェクトのコアになる機能を示す|
|`@Repositry`| データアクセスオブジェクト*1を示す|
|`@Autowired`|依存関係の自動注入をする。コンストラクタ、ゲッタセッタに付けると依存関係を自動解決してくれる| 
|`@Valu`|設定ファイルや環境変数から値を取得し、他のBeanに注入する|
|`@Configration`|DIコンテナの設定をJavaベースで記入する| 

*1 **データアクセスオブジェクト**
データベースなどに対してデータアクセスをする機構を抽象化し、ビジネスロジックから分離するデザインパターン
こうすることで、データベース側の詳細な実装や利用方法を隠蔽する。

他にもまだまだあるようですが、リファレンスなどを見て適宜適切に使っていきたいですね！



## アプリケーションコンテキスト
さぁ、ついにやってきました**アプリケーションコンテキスト**です。
そもそもアプリケーションコンテキストというのは、Springによって管理されるオブジェクトの集合です。
設定情報からオジェクトのインスタンスまで、Springで作られたオブジェクトを一元的に管理しています。
アプリケーションコンテキストの役割は以下のようになっています。
**1.Beanの作成と管理**
設定情報に基づいてBeanオブジェクトを作成し管理します。
**2.依存関係の解決**
Bean間の依存関係の解決を自動的に行います。
開発者は手動で依存関係を弄ることなく開発に注力できます。
**3.設定情報の管理**
データベース接続の設定やサードパーティ製ライブラリの設定を管理してくれます。それらはXML、アノテーション、Javaベースの設定クラスなどの形で提供することができる
**4.ライフサイクルの管理**
Beanのライフサイクルを自動的に管理できます。Beanの作成、初期化、利用時の注入、破棄を必要に応じて実行することができます。
**5.リソースの管理**
データベース接続や、ファイルシステムなどのリソース管理を行います。ユーザーはリソースアクセスの管理を簡単にすることができ、アプリケーション内での共通化と一貫性を実現できます。

これらの機能を提供してくれるアプリケーションコンテキストは、想像の通り**SpringFrameworkを利用するうえで基盤となる概念**です。
なので、この部分は特にしっかりと理解しておく必要があるでしょう。


## あとがき
どうだったでしょうか？
Springでよく出てくるワードを事前知識として勉強しながら書いてみました。
個人的には依然理解できなかったDIが腑に落ちる形で理解できたのがよかったです。
次回以降は本格的にSpringの機能について触れていくことになると思うので、これらの概念はしっかり理解しておくようにしたいですね。