spring
依存性注入(DI)および制御反転(IoC)
サーチ…
備考
大規模なソフトウェアアプリケーションのソースコードは、通常、複数のユニットに編成されています。ユニットの定義は、通常、使用されるプログラミング言語によって異なります。例えば、手続き型プログラミング言語(Cのような)で書かれたコードは、 functions
またはprocedures
編成される。同様に、オブジェクト指向プログラミング言語(Java、Scala、C#など)のコードは、 classes
、 interfaces
などに編成されていclasses
。これらのコード構成単位は、ソフトウェアアプリケーション全体を構成する個々の単位と考えることができます。
アプリケーションが複数のユニットを持つ場合、それらのユニット間の依存関係は、あるユニットが他のユニットを使用してその機能を完了しなければならない場合に発生します。依存単位は、 consumers
と、特定の機能のproviders
として依存する単位と考えることができます。
最も簡単なプログラミングアプローチは、アプリケーションの全体的な実行のどの時点でどのプロバイダをインスタンス化し、使用し、破壊するかを決定することによって、消費者がソフトウェアアプリケーションのフローを完全に制御することです。消費者は、消費者のdependencies
である実行フロー中にプロバイダを完全に制御できると言われています。プロバイダが独自の依存関係を持っている場合、消費者はプロバイダをどのように初期化(および解放)するべきかを心配する必要があり、ソフトウェアのユニット数が増えるにつれて制御フローがますます複雑になります。このアプローチはまた、ユニット間のカップリングも増加させるため、ソフトウェアの他の部分を破壊することを心配することなくユニットを個別に変更することがますます困難になっています。
Inversion of Control (IoC)は、単位発見、インスタンス化、破壊などの制御フローアクティビティを消費者やプロバイダとは独立したフレームワークにアウトソーシングすることを提唱する設計原理です。 IoCの基本原則は、消費者とプロバイダを切り離し、ソフトウェア部門が依存関係の発見、インスタンス化、クリーンアップを心配する必要がなくなり、ユニットがそれぞれの機能に集中できるようにすることです。このデカップリングは、ソフトウェアの拡張性と保守性を維持するのに役立ちます。
依存性注入は、依存性(プロバイダ)のインスタンスが、消費者がそれらを見つけてインスタンス化する代わりに、ソフトウェアユニット(消費者)に注入される制御原理の逆転を実装する技術の1つである。
Springフレームワークには、Spring管理されたBeanを依存関係として他のSpring管理Beanに注入できるようにする、そのコアに依存性注入モジュールが含まれています。
XML構成を使用して手動で依存性を注入する
次のJavaクラスを考えてみましょう。
class Foo {
private Bar bar;
public void foo() {
bar.baz();
}
}
見て分かるように、クラスFoo
は、メソッドfoo
が正常に動作するために、別のクラスBar
インスタンスに対してメソッドbaz
を呼び出す必要があります。 Bar
の依存関係であると言われてFoo
ため、 Foo
なくても正常に動作することはできませんBar
インスタンス。
コンストラクタインジェクション
SpringフレームワークのXML構成を使用してSpring管理Beanを定義する場合、 Foo
型のBeanは次のように構成できます。
<bean class="Foo">
<constructor-arg>
<bean class="Bar" />
</constructor-arg>
</bean>
または(より詳細に)
<bean id="bar" class="bar" />
<bean class="Foo">
<constructor-arg ref="bar" />
</bean>
両方の場合において、スプリングフレームワークは、最初のインスタンス作成Bar
とinjects
のインスタンスにそれをFoo
。この例では、クラスFoo
、パラメータとしてBar
インスタンスを取るコンストラクタがあることを前提としています。
class Foo {
private Bar bar;
public Foo(Bar bar) { this.bar = bar; }
}
このスタイルは、依存関係( Bar
インスタンス)がクラスコンストラクタに注入されているため、 コンストラクタインジェクションとして知られています。
特性注入
Bar
依存関係をFoo
に挿入するもう1つの方法は、次のとおりです。
<bean class="Foo">
<property name="bar">
<bean class="Bar" />
</property>
</bean>
または(より詳細に)
<bean id="bar" class="bar" />
<bean class="Foo">
<property name="bar" ref="bar" />
</bean>
これには、 Foo
クラスに次のようなBar
インスタンスを受け入れるセッターメソッドが必要です。
class Foo {
private Bar bar;
public void setBar(Bar bar) { this.bar = bar; }
}
Java構成を使用して手動で依存性を注入する
上記のXML構成の例は、次のようにJava構成で書き直すことができます。
コンストラクタインジェクション
@Configuration
class AppConfig {
@Bean
public Bar bar() { return new Bar(); }
@Bean
public Foo foo() { return new Foo(bar()); }
}
特性注入
@Configuration
class AppConfig {
@Bean
public Bar bar() { return new Bar(); }
@Bean
public Foo foo() {
Foo foo = new Foo();
foo.setBar(bar());
return foo;
}
}
XML設定による依存関係のオートワイヤリング
依存関係は、Springフレームワークのコンポーネントスキャン機能を使用するときに自動的に呼び出されます。オートワイヤリングを機能させるには、次のXML設定を行う必要があります。
<context:annotation-config/>
<context:component-scan base-package="[base package]"/>
ここで、 base-package
はSpringがコンポーネントスキャンを実行する完全修飾Javaパッケージです。
コンストラクタインジェクション
依存関係は、次のようにクラスコンストラクタを通じて注入できます。
@Component
class Bar { ... }
@Component
class Foo {
private Bar bar;
@Autowired
public Foo(Bar bar) { this.bar = bar; }
}
ここで、 @Autowired
はSpring固有のアノテーションです。 SpringはJSR-299もサポートし、他のJavaベースの依存性注入フレームワークへのアプリケーション移植性を可能にします。これにより、 @Autowired
を@Inject
に置き換えることができます:
@Component
class Foo {
private Bar bar;
@Inject
public Foo(Bar bar) { this.bar = bar; }
}
特性注入
依存関係は、次のようにsetterメソッドを使用して注入することもできます。
@Component
class Foo {
private Bar bar;
@Autowired
public void setBar(Bar bar) { this.bar = bar; }
}
フィールドインジェクション
Autowiringでは、クラスインスタンス内のフィールドを次のように直接初期化することもできます。
@Component
class Foo {
@Autowired
private Bar bar;
}
Springバージョン4.1+では、オプションの依存関係のためにOptionalを使用できます。
@Component
class Foo {
@Autowired
private Optional<Bar> bar;
}
コンストラクタDIにも同じアプローチを使用できます。
@Component
class Foo {
private Optional<Bar> bar;
@Autowired
Foo(Optional<Bar> bar) {
this.bar = bar;
}
}
Java設定による依存関係の自動配線
Java構成によるコンストラクター注入は、次のような自動配線を利用することもできます。
@Configuration
class AppConfig {
@Bean
public Bar bar() { return new Bar(); }
@Bean
public Foo foo(Bar bar) { return new Foo(bar); }
}