2つの例を通してそれを理解してみましょう。
例1
以前のアプリは、コマンドプロンプトを生成して、ユーザー入力を次々に受け入れていました。現在、UIフレームワークはさまざまなUI要素をインスタンス化し、それらのUI要素のさまざまなイベント(マウスホバー、クリックなど)をループし、ユーザー/メインプログラムはそれらのイベントをリッスンするためのフック(JavaのUIイベントリスナーなど)を提供します。そのため、メインUI要素フローの「コントロール」は、ユーザープログラムからUIフレームワークに移動します。以前は、ユーザープログラムにありました。
例2
CustomerProcessor
以下のクラスを検討してください。
class CustomerProcessor
{
SqlCustRepo custRepo = new SqlCustRepo();
private void processCustomers()
{
Customers[] custs = custRepo.getAllCusts();
}
}
私がしたい場合processCustomer()
のいずれかの実装に依存しないようにgetAllCusts()
が提供するものだけではなく、SqlCustRepo
私はラインを取り除く必要がありますSqlCustRepo custRepo = new SqlCustRepo()
し、そのような実装のさまざまな種類を受け入れることができる、より汎用的なもの、と交換processCustomers()
するだけのために動作します提供された実装。上記のコード(SqlCustRepo
メインプログラムロジックによる必要なクラスのインスタンス化)は従来の方法でありprocessCustomers()
、の実装から切り離すというこの目標を達成しませんgetAllCusts()
。制御の反転では、コンテナは必要な実装クラスをインスタンス化し(xml設定などで指定)、メインプログラムロジックに挿入し、指定されたフックごとにバインドします(たとえば、スプリングフレームワークの@Autowired
アノテーションまたは getBean()
メソッドによって)。
これがどのように行われるかを見てみましょう。以下のコードを検討してください。
Config.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="custRepo" class="JsonCustRepo" />
</beans>
CustRepo.java
interface ICustRepo
{ ... }
JsonCustRepo.java
class JsonCustRepo implements CustRepo
{ ... }
App.java
class App
{
public static void main(String[] args)
{
ApplicationContext context = new ClassPathXmlApplicationContext("Config.xml");
ICustRepo custRepo = (JsonCustRepo) context.getBean("custRepo");
}
}
私たちも持つことができます
class GraphCustRepo implements ICustRepo { ... }
そして
<bean id="custRepo" class="GraphCustRepo">
App.javaを変更する必要はありません。
コンテナ(Springフレームワーク)の上には、xmlファイルをスキャンし、特定のタイプのBeanをインスタンス化し、それをユーザープログラムに挿入する責任があります。ユーザープログラムは、どのクラスをインスタンス化するかを制御できません。
PS:IoCは一般的な概念であり、多くの方法で達成されます。上記の例は、依存性注入によって実現しています。
参照: Martin Fowlerの記事。