JavaRush /Курсы /Модуль 5. Spring /Примеры внедрения зависимостей

Примеры внедрения зависимостей

Модуль 5. Spring
3 уровень , 6 лекция
Открыта

В следующем примере используются конфигурационные метаданные на основе XML для DI на основе сеттера. Небольшая часть конфигурационного файла Spring XML задает некоторые определения бинов следующим образом:

<bean id="exampleBean" class="examples.ExampleBean">
    <!-- внедрение через сеттер с использованием вложенного элемента ref -->
    <property name="beanOne">
        <ref bean="anotherExampleBean"/>
    </property>
    <!-- внедрение через сеттер с использованием более точного атрибута ref -->
    <property name="beanTwo" ref="yetAnotherBean"/>
    <property name="integerProperty" value="1"/>
</bean>
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

В следующем примере показан соответствующий класс ExampleBean:

Java
public class ExampleBean {
    private AnotherBean beanOne;
    private YetAnotherBean beanTwo;
    private int i;
    public void setBeanOne(AnotherBean beanOne) {
        this.beanOne = beanOne;
    }
    public void setBeanTwo(YetAnotherBean beanTwo) {
        this.beanTwo = beanTwo;
    }
    public void setIntegerProperty(int i) {
        this.i = i;
    }
}
Kotlin
class ExampleBean {
    lateinit var beanOne: AnotherBean
    lateinit var beanTwo: YetAnotherBean
    var i: Int = 0
}

В предыдущем примере сеттеры объявлены для сопоставления со свойствами, указанными в XML-файле. В следующем примере используется DI на основе конструктора:

<bean id="exampleBean" class="examples.ExampleBean">
    <!-- внедрение через конструктор с использованием вложенного элемента ref -->
    <constructor-arg>
        <ref bean="anotherExampleBean"/>
    </constructor-arg>
    <!-- внедрение через конструктор с использованием более точного атрибута ref -->
    <constructor-arg ref="yetAnotherBean"/>
    <constructor-arg type="int" value="1"/>
</bean>
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

В следующем примере показан соответствующий класс ExampleBean:

Java
public class ExampleBean {
    private AnotherBean beanOne;
    private YetAnotherBean beanTwo;
    private int i;
    public ExampleBean(
        AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
        this.beanOne = anotherBean;
        this.beanTwo = yetAnotherBean;
        this.i = i;
    }
}
Kotlin
class ExampleBean(
        private val beanOne: AnotherBean,
        private val beanTwo: YetAnotherBean,
        private val i: Int)

Аргументы конструктора, заданные в определении бина, используются в качестве аргументов конструктора ExampleBean.

Теперь рассмотрим вариант этого примера, в котором вместо использования конструктора Spring предлагается вызвать ститический фабричный метод для возврата экземпляра объекта:

<bean id="exampleBean" class="examples.ExampleBean" factory-method="createInstance">
    <constructor-arg ref="anotherExampleBean"/>
    <constructor-arg ref="yetAnotherBean"/>
    <constructor-arg value="1"/>
</bean>
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

В следующем примере показан соответствующий класс ExampleBean:

Java
public class ExampleBean {
    // закрытый (приватный) конструктор
    private ExampleBean(...) {
        ...
    }
    // статический фабричный метод; аргументами этого метода могут считаться
    // зависимости возвращаемого бина,
    // независимо от того, как эти аргументы фактических используются.
    public static ExampleBean createInstance (
        AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
        ExampleBean eb = new ExampleBean (...);
        // некоторые другие операции...
        return eb;
    }
}
Kotlin
class ExampleBean private constructor() {
    companion object {
        // статический фабричный метод; аргументами этого метода могут считаться
        // зависимости возвращаемого бина,
        // независимо от того, как эти аргументы фактических используются.
        @JvmStatic
        fun createInstance(anotherBean: AnotherBean, yetAnotherBean: YetAnotherBean, i: Int): ExampleBean {
            val eb = ExampleBean (...)
            // некоторые другие операции...
            return eb
        }
    }
}

Аргументы для статического фабричного метода предоставляются элементами <constructor-arg/>, точно так же, как если бы на самом деле использовался конструктор. Тип класса, возвращаемого фабричным методом, не обязательно должен быть того же типа, что и класс, содержащий статический фабричный метод (хотя в данном примере это так). Экземплярный (нестатический) фабричный метод может быть использован практически идентичным образом (за исключением использования атрибута factory-bean вместо атрибута class), поэтому здесь эти нюансы не рассматриваются.

Комментарии (10)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Родион Уровень 113
14 августа 2025
ститический фабричный метод
Сергей Уровень 21
22 марта 2023
и на сколько вобще актульно щас в xml изучать это все? здается мне что нам впаривают какую то дичь
Эльвина Уровень 1
14 июня 2023
я сейчас работаю в организации, дали проект, а там все бины в xml, так что такое тоже можно встретить, оказывается)
11 сентября 2023
Багато ентепрайзів працюють на застралілому коді, який не бачив рефактору роками. Тому якщо потрапите у компанію яка пітримує такий проект, то доведеться стикатися із такими динозаврами.
Yarik Уровень 44
24 февраля 2023
После долгого изучения различной поверхностной информации, этот курс очень помогает расставить все по местам.
Will Fight Уровень 27
16 февраля 2023
ститический фабричный метод
Igor Уровень 108 Expert
10 февраля 2023
Почему в первом примере, когда используем сеттеры, то имя в xml :

<property name="integerProperty" value="1"/>
не совпадает с именем поля в самом классе:

private int i;

хотя имена первых двух полей одинаковые
Владимир (koloncovvova@mail.ru) Уровень 108 Expert
12 февраля 2023
Если мне не изменяет память, то в xml имя можно любое задавать, с полем не обязано совпасть. Когда класс правильно помечен, там Спринг сам поймет, кто есть кто.
Денис Уровень 108 Expert
13 февраля 2023
Потому что мы должны СТРОГО использовать имя сеттера, без слова set и с маленькой буквы. Спринг сам добавляет set и делает маленькую букву заглавной. Вот как в этой статье. public void setIntegerProperty(int i) { this.i = i; } <property name="integerProperty" value="1"/> Другой пример, если бы у нас был такой сеттер public void setWhatYouWant(int i) { this.i = i; } То XML была бы такой <property name="whatYouWant" value="1"/>
Igor Уровень 108 Expert
14 февраля 2023
Спасибо большое за ответы! Стало понятнее теперь. Получается Спринг смотрит на имя сеттера и сравнивает его с property name в xml файле, т.е. ему все равно как это поле называется в самом классе.