DI з урахуванням конструктора виконується шляхом виклику контейнером конструктора з низкою аргументів, кожен із яких представляє залежність. Виклик статичного фабричного методу з певними аргументами для створення біна майже еквівалентний, і в цьому аналізі аргументи конструктора і статичного фабричного методу розглядаються однаково. У наступному прикладі показаний клас, залежність до якого може бути впроваджена виключно через конструктор:

Java
public class SimpleMovieLister {
    // SimpleMovieLister має залежність від MovieFinder
    private final MovieFinder movieFinder;
    // конструктор для того, щоб контейнер Spring міг впровадити MovieFinder
    public SimpleMovieLister(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
    // Бізнес-логіка, яка фактично використовує впроваджений MovieFinder, опущена...
}
Kotlin
// конструктор для того, щоб контейнер Spring міг впровадити MovieFinder
class SimpleMovieLister(private val movieFinder: MovieFinder) {
    // Бізнес-логіка, яка фактично використовує впроваджений MovieFinder, опущена...
}

Зверни увагу, що в цьому класі немає нічого особливого. Це POJO (простий об'єкт мови Java), який не залежить від конкретних інтерфейсів контейнера, базових класів або анотацій.

Дозволення аргументів конструктора

Зіставлення дозволення аргументу конструктора відбувається з використанням типу аргументу. Якщо в аргументах конструктора визначення біна немає потенційної неоднозначності, то порядок, у якому аргументи конструктора встановлені у визначенні біна, є порядком, у якому ці аргументи передаються відповідному конструктору під час створення біна. Розглянемо наступний клас:

Java
package x.y;
public class ThingOne {
    public ThingOne(ThingTwo thingTwo, ThingThree thingThree) {
        // ...
    }
}
Kotlin
package x.y
class ThingOne(thingTwo: ThingTwo, thingThree: ThingThree)

Якщо припустити, що класи ThingTwo та ThingThree не пов'язані успадкуванням, то потенційної двозначності не виникає. Таким чином, наступна конфігурація працює нормально, і не потрібно чітко вказувати індекси або типи аргументів конструктора в елементі <constructor-arg/>.

<beans>
    <bean id="beanOne" class="x.y.ThingOne">
        <constructor-arg ref="beanTwo"/>
        <constructor-arg ref="beanThree"/>
    </bean>
    <bean id="beanTwo" class="x.y.ThingTwo"/>
    <bean id="beanThree" class="x.y.ThingThree"/>
</beans>

Якщо посилання надається на інший бін, то тип відомий, тому може відбутися зіставлення (як це було в попередньому прикладі). Якщо використовується простий тип, наприклад <value>true</value>, Spring не може визначити тип значення, і тому не може виконати зіставлення за типом без сторонньої допомоги. Розглянемо наступний клас:

Java
package examples;
public class ExampleBean {
    // Кількість років до розрахунку остаточної відповіді
    private final int years;
    // Відповідь на головне питання життя, всесвіту і всього такого
    private final String ultimateAnswer;
    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }
}
Kotlin
package examples
class ExampleBean(
    private val years: Int, // Кількість років для розрахунку остаточної відповіді
    private val ultimateAnswer: String // Відповідь на головне питання життя, всесвіту і всього такого
)
Зіставлення типів аргументів конструктора

У попередньому сценарії контейнер може задіяти зіставлення типів із простими типами, якщо тип аргументу конструктора явно вказаний за допомогою атрибуту type, як показано в наступному прикладі:

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg type="java.lang.String" value="42"/>
</bean>
Індекс аргументу конструктора

Ти можеш використовувати атрибут index, щоб явно вказати індекс аргументів конструктора, як показано в наступному прикладі:

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg index="0" value="7500000"/>
    <constructor-arg index="1" value="42"/>
</bean>

Окрім усунення неоднозначності кількох простих значень, зазначення індексу усуває неоднозначність, якщо конструктор має два аргументи одного типу.

Індекс ґрунтується на 0 (починається з 0).
Ім'я аргументу конструктора

Також можна використовувати ім'я параметра конструктора для усунення суперечностей значень, як показано в наступному прикладі:

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg name="years" value="7500000"/>
    <constructor-arg name="ultimateAnswer" value="42"/>
</bean>

Май на увазі: щоб це працювало "з коробки", код повинен бути скомпільований з увімкненим прапорцем налагодження (debug), щоб Spring міг знайти ім'я параметра в конструкторі. Якщо ти не можеш або не хочеш компілювати свій код з прапорцем налагодження, можна використовувати анотацію @ConstructorProperties JDK для явного іменування аргументів твого конструктора. Тоді зразок класу має виглядати так:

Java
package examples;
public class ExampleBean {
    // Поля опущені
    @ConstructorProperties({"years", "ultimateAnswer"})
    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }
}
Kotlin
package examples
class ExampleBean
@ConstructorProperties("years", "ultimateAnswer")
constructor(val years: Int, val ultimateAnswer: String)