Поиск…


Singleton scope

Если бит определен с помощью Singleton scope, в контейнере Spring будет создан только один экземпляр объекта. Все запросы к этому компоненту будут возвращать один и тот же общий экземпляр. Это значение по умолчанию при определении компонента.

Учитывая следующий класс MyBean:

public class MyBean {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyBean.class);
    private String property;

    public MyBean(String property) {
        this.property = property;
        LOGGER.info("Initializing {} bean...", property);
    }

    public String getProperty() {
        return this.property;
    }

    public void setProperty(String property) {
        this.property = property;
    }
}

Мы можем определить одноэлементный компонент с аннотацией @Bean:

@Configuration
public class SingletonConfiguration {

    @Bean
    public MyBean singletonBean() {
        return new MyBean("singleton");
    } 
}

В следующем примере дважды извлекается один и тот же компонент из контекста Spring:

MyBean singletonBean1 = context.getBean("singletonBean", MyBean.class);
singletonBean1.setProperty("changed property");

MyBean singletonBean2 = context.getBean("singletonBean", MyBean.class);

При регистрации свойства singletonBean2 будет отображаться сообщение «измененное свойство» , так как мы просто получили один и тот же общий экземпляр.

Поскольку экземпляр разделяется между различными компонентами, рекомендуется определить область одиночной развертки для объектов без состояния.

Ленивые однополюсные бобы

По умолчанию одноэлементные компоненты предварительно создаются. Следовательно, экземпляр общего объекта будет создан при создании контейнера Spring. Если мы запустим приложение, появится сообщение «Инициализация однопользовательского бина ...» .

Если мы не хотим, чтобы bean был предварительно создан, мы можем добавить аннотацию @Lazy к определению bean-компонента. Это предотвратит создание компонента до его первой запроса.

@Bean
@Lazy
public MyBean lazySingletonBean() {
    return new MyBean("lazy singleton");
}

Теперь, если мы запустим контейнер Spring, не появится сообщение «Инициализация ленивого одноэлементного ...» . Боб не будет создан до тех пор, пока он не будет запрошен в первый раз:

logger.info("Retrieving lazy singleton bean...");
context.getBean("lazySingletonBean");

Если мы запустим приложение как с однопользовательскими, так и с ленивыми одноэлементными бобами, оно будет вызывать следующие сообщения:

Initializing singleton bean...
Retrieving lazy singleton bean...
Initializing lazy singleton bean...

Область прототипа

Контейнер с прототипом не создается заранее при запуске Spring. Вместо этого новый новый экземпляр будет создаваться каждый раз, когда запрос на получение этого компонента отправляется в контейнер. Эта область рекомендуется для объектов с сохранением состояния, так как ее состояние не будет использоваться другими компонентами.

Чтобы определить компонент с прототипом, нам нужно добавить аннотацию @Scope, указав тип требуемой области.

Учитывая следующий класс MyBean:

public class MyBean {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyBean.class);
    private String property;

    public MyBean(String property) {
        this.property = property;
        LOGGER.info("Initializing {} bean...", property);
    }

    public String getProperty() {
        return this.property;
    }

    public void setProperty(String property) {
        this.property = property;
    }
}

Мы определяем определение bean-компонента, указав его область действия как прототип:

@Configuration
public class PrototypeConfiguration {

    @Bean
    @Scope("prototype")
    public MyBean prototypeBean() {
        return new MyBean("prototype");
    }
}

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

MyBean prototypeBean1 = context.getBean("prototypeBean", MyBean.class);
prototypeBean1.setProperty("changed property");

MyBean prototypeBean2 = context.getBean("prototypeBean", MyBean.class);

logger.info("Prototype bean 1 property: " + prototypeBean1.getProperty());
logger.info("Prototype bean 2 property: " + prototypeBean2.getProperty());

Посмотрев следующий результат, мы увидим, как был создан новый экземпляр для каждого запроса bean-компонента:

Initializing prototype bean...
Initializing prototype bean...
Prototype bean 1 property: changed property
Prototype bean 2 property: prototype

Распространенная ошибка заключается в том, чтобы предположить, что бонус воссоздается за вызов или за поток, это НЕ так. Вместо этого создается экземпляр PER INJECTION (или поиск из контекста). Если ботанический объект с прототипом только инжектируется только в один синглетный компонент, всегда будет только один экземпляр этого компонента с прототипом.

Spring не управляет полным жизненным циклом прототипа: контейнер создает, настраивает, украшает и иным образом собирает прототип объекта, передает его клиенту, а затем больше не знает об этом экземпляре прототипа.

Дополнительные области в контекстно-зависимых контекстах

Существует несколько областей, доступных только в контексте приложений, ориентированных на веб-интерфейс:

  • request - новый экземпляр bean создается для HTTP-запроса
  • session - создается новый экземпляр bean для сеанса HTTP
  • application - создается новый экземпляр bean для ServletContext
  • globalSession - новый экземпляр bean создается на глобальный сеанс в среде Portlet (в глобальной среде сеанса Servlet равно области сеанса)
  • websocket - создается новый экземпляр bean для сеанса WebSocket

Никакая дополнительная настройка не требуется для объявления и доступа к фасолям с веб-областью в среде Spring Web MVC.

Конфигурация XML

<bean id="myRequestBean" class="OneClass" scope="request"/>
<bean id="mySessionBean" class="AnotherClass" scope="session"/>
<bean id="myApplicationBean" class="YetAnotherClass" scope="application"/>
<bean id="myGlobalSessionBean" class="OneMoreClass" scope="globalSession"/>

Конфигурация Java (до весны 4.3)

@Configuration
public class MyConfiguration {

    @Bean
    @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public OneClass myRequestBean() {
        return new OneClass();
    }

    @Bean
    @Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public AnotherClass mySessionBean() {
        return new AnotherClass();
    }

    @Bean
    @Scope(value = WebApplicationContext.SCOPE_APPLICATION, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public YetAnotherClass myApplicationBean() {
        return new YetAnotherClass();
    }

    @Bean
    @Scope(value = WebApplicationContext.SCOPE_GLOBAL_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public OneMoreClass myGlobalSessionBean() {
        return new OneMoreClass();
    }
}

Конфигурация Java (после весны 4.3)

@Configuration
public class MyConfiguration {

    @Bean
    @RequestScope
    public OneClass myRequestBean() {
        return new OneClass();
    }

    @Bean
    @SessionScope
    public AnotherClass mySessionBean() {
        return new AnotherClass();
    }

    @Bean
    @ApplicationScope
    public YetAnotherClass myApplicationBean() {
        return new YetAnotherClass();
    }
}

Компоненты, обработанные аннотацией

@Component
@RequestScope
public class OneClass {
    ...
}

@Component
@SessionScope
public class AnotherClass {
    ...
}

@Component
@ApplicationScope
public class YetAnotherClass {
    ...
}

@Component
@Scope(scopeName = WebApplicationContext.SCOPE_GLOBAL_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class OneMoreClass {
    ...
}

@Component
@Scope(scopeName = "websocket", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class AndOneMoreClass {
    ...
}


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow