Spring IoC контейнер: зависимости, инъекция метода

В большинстве сценариев применения большинство бинов в контейнере являются синглтонами. Когда синглтону необходимо сотрудничать с другим синглтоном или не-синглтон компоненту необходимо сотрудничать с другим не-синглтон компонентом, вы обычно обрабатываете зависимость, определяя один компонент как свойство другого. Проблема возникает, когда жизненные циклы бинов различны. Предположим, что синглтон компоненту A нужно использовать не-синглтон (прототип) компонент B, возможно, при каждом вызове метода в A. Контейнер создает синглтон компонент A только один раз и, таким образом, получает только одну возможность установить свойства. Контейнер не может предоставить компоненту A новый экземпляр компонента B каждый раз, когда он нужен.

Решение состоит в том, чтобы отказаться от некоторой инверсии контроля. Вы можете сделать так, чтобы компонент A узнал о контейнере, реализовав интерфейс ApplicationContextAware и сделав вызов getBean("B") для контейнера, запрашивая (как правило, новый) экземпляр компонента B каждый раз, когда это требуется компоненту A. В следующем примере показан этот подход:

Java

// класс, который использует класс с состоянием Command-style для выполнения некоторой обработки
package fiona.apple;

// Spring-API imports
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class CommandManager implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    public Object process(Map commandState) {
        // захватить новый экземпляр соответствующего Command
        Command command = createCommand();
        // устанавливаем состояние (ожидаемо, нового) экземпляра Command
        command.setState(commandState);
        return command.execute();
    }

    protected Command createCommand() {
        // обратите внимание на Spring API зависимость!
        return this.applicationContext.getBean("command", Command.class);
    }

    public void setApplicationContext(
            ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

Kotlin

// класс, который использует класс с состоянием Command-style для выполнения некоторой обработки
package fiona.apple

// Spring-API imports
import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationContextAware

class CommandManager : ApplicationContextAware {

    private lateinit var applicationContext: ApplicationContext

    fun process(commandState: Map<*, *>): Any {
        // захватить новый экземпляр соответствующего Command
        val command = createCommand()
        // устанавливаем состояние (ожидаемо, нового) экземпляра Command
        command.state = commandState
        return command.execute()
    }

    // обратите внимание на Spring API зависимость!
    protected fun createCommand() =
            applicationContext.getBean("command", Command::class.java)

    override fun setApplicationContext(applicationContext: ApplicationContext) {
        this.applicationContext = applicationContext
    }
}

Предыдущее нежелательно, поскольку бизнес-код осведомлен о Spring Framework и связан с ним. Внедрение метода, несколько расширенная функция контейнера IoC Spring, позволяет аккуратно обрабатывать этот сценарий использования.


Читайте также:


Комментарии

Популярные сообщения из этого блога

Методы класса Object в Java

Как получить текущий timestamp в Java

Основные опции JVM для повышения производительности и отладки