はじめに
この記事は依存性の注入の概念に集中するため、
なぜ依存性の注入を使うのかメリットは何かは詳しく説明しないです。
依存性の注入(Dependency Injection)とは?
定義
依存性の注入(Dependency Injection)、もしくは依存性注入、依存注入、DIと呼ばれています。
Wikipediaにより、依存性の注入とはあるオブジェクトや関数が、
依存する他のオブジェクトや関数を受け取るデザインパターンであると書いてありますが、
なかなか理解しづらいですね、、、
具体的な例
それでは現実の物を使って理解しましょう。
例えば、車はエンジンがないと動けないので、この時に車はエンジンに依存すると言えるでしょう。
(エンジンは車の依存)
こういう関係は依存性と言います。これだけです。
依存性の注入を使わない場合
車(Car)とエンジン(Engine)をJavaのコードで見てみましょう。
class Car {
private Engine engine;
public Car(){
engine = new Engine();
}
public void run(){
engine.start();
}
}
Carクラスの中では直接Engineクラスをインスタンス化するため、
もしエンジンの種類を変更したい場合は、Carクラスの作成時にすでにエンジンの種類を指定しているため、変更することが面倒くさいです。
例えば、車作った時に内部は既にディーゼルエンジンを装置したのに、
それ以降ガソリンエンジンに変更したかったら、どう考えてもやりたくないですねw
依存性の注入を使う場合
同じ車(Car)とエンジン(Engine)の例をJavaのコードで見てみましょう。
class Car {
private Engine engine;
public Car(Engine engine){
this.engine = engine;
}
public void run(){
engine.start();
}
}
この書き方でEngineオブジェクトは外部から注入することが可能となり、
クラス間の依存関係が単純化されるだけでなく、Carクラスのテストもしやすくなります。
例えば、車作ってからエンジンの種類を決めると、その時にどんなエンジンでも自由に選べるでしょう。
つまり、車自体はエンジンに依存しなくなりました!!
じゃあ依存性の注入の注入とは?
依存性の注入の注入は以下のコードで見ましょう!
Engine engine = new Engine(); // ここでインスタンス化したengineを
Car car = new Car(engine); // Car()の中にCar(engine)←こう注入する!
car.run();
この方法はコンストラクター(constructor)注入と呼ばれ、依存性注入の一般的な実装です。
これにより、インスタンス(Car)が作成されるときに依存性(Engine)が正しく注入されることを保証できます。
他にはセッター(setter)注入とフィールド(field)注入という方法もあります。
// セッター(setter)注入
Engine engine = new Engine();
Car car = new Car();
car.setEngine(engine);
car.run();
// フィールド(field)注入
Engine engine = new Engine();
Car car = new Car();
car.engine = engine;
car.run();
セッター注入とフィールド注入はインスタンス化してから依存性を注入するため、
実行時に依存関係が注入されない可能性があります。
したがって、実務では依存性が正しく注入されるため、コンストラクタ注入を多く使ってます。
終わりに
Spring Bootの @Autowired
を使えば、
Engine engine = new Engine();
すら書かなくていいです!(自動的に生成してくれるので)
最後、
この記事はとにかく現実の例で依存性の注入をわかりやすく伝えたいだけです!