Skip to content

3. Інверсія контролю IoC

Тепер зупинимося на понятті інверсії контролю (IoC, Inversion of Control), яке використовує Spring для налаштування додатків. Щоб проілюструвати цю концепцію, повернімося до архітектури нашого попереднього тестового додатка:

Щоб отримати доступ до даних SGBD, тестовий клас повинен використовувати сервіси об’єкта, що реалізує інтерфейс [IArticlesDao], наприклад, об’єкта типу [ArticlesDaoPlainODBC]. Ми розглянули два можливі варіанти створення екземпляра такого об’єкта:

  • у першому варіанті тестовий клас сам ініціював створення екземпляра об’єкта типу [ArticlesDaoPlainODBC]:
    <TestFixture()> _
    Public Class NunitTestArticlesDaoPlainOdbc

         ' об'єкт, що тестується
        Private articlesDao As IArticlesDao

        <SetUp()> _
        Public Sub init()
             ' створюємо екземпляр об’єкта, що тестується
            articlesDao = New ArticlesDaoPlainODBC("odbc-firebird-articles", "SYSDBA", "masterkey")
        End Sub
...
    End Class

У коді є жорстка залежність від імені класу. Якщо клас реалізації інтерфейсу [IArticlesDao] зміниться, код методу [init] доведеться змінити. Між об’єктами існують такі взаємозв’язки:

Клас [NunitTestArticlesDaoPlainOdbc] самостійно ініціює створення об’єкта [ArticlesDaoPlainODBC], який йому потрібен. Повертаючись до терміна «інверсія контролю», можна сказати, що саме він має «контроль» над створенням об’єкта, який йому потрібен.

  • Другий варіант працює інакше. Тестовий клас тепер виглядає так:
    <TestFixture()> _
    Public Class NunitSpringTestArticlesDaoPlainOdbc

         ' об'єкт, що тестується
        Private articlesDao As IArticlesDao

        <SetUp()> _
        Public Sub init()
       ' отримуємо екземпляр Spring-генератора об’єктів
            Dim factory As XmlObjectFactory = New XmlObjectFactory(New FileStream("spring-config-plainodbc.xml", FileMode.Open))
       ' запитуємо створення екземпляра об’єкта DAO «articles»
            articlesDao = CType(factory.GetObject("articlesdao"), IArticlesDao)
        End Sub
    ...
    End Class

Цей механізм можна схематично зобразити так:

Тут тестовий клас не бере на себе ініціативу вимагати створення об’єкта [ArticlesDaoPlainODBC]. Він обмежується тим, що запитує у Spring посилання на такий об’єкт. Якщо об’єкт існує, Spring повертає посилання на нього. Якщо його немає, Spring створює його. Тестовий клас втратив контроль над створенням об’єкта [ArticlesDaoPlainODBC]. Він просто запитує посилання на цей об’єкт. Цей запит у даному випадку змусить Spring створити об’єкт. Але можна уявити, що в іншому контексті запитуваний об’єкт уже був створений на запит додатка. У такому разі Spring не створює об’єкт заново, а повертає посилання на вже існуючий об’єкт (синглтон). Поняття «інверсія контролю» (IoC) у цьому контексті означає:

  • додаток ніколи не бере на себе ініціативу щодо створення необхідних йому синглетонів. Він просто запитує посилання на них.
  • саме Spring приймає рішення про створення синглтона під час першого запиту на посилання на нього