В мастерской Spring трудились умелые и старательные помощники — бины. Каждый из них был наделен своей уникальной задачей: кто-то создавал игрушки, кто-то сортировал конфеты, а кто-то выращивал яркие цветы.
Чтобы работа мастерской была упорядоченной и эффективной, для бинов были установлены четкие правила — скоупы. Эти правила определяли, как долго бины могли существовать и сколько экземпляров одного вида должно быть создано одновременно. Благодаря этим волшебным рамкам мастерская работала слаженно и надежно.
Прототип (Prototype): Ежик-пекарь
Ежик-пекарь каждый раз, когда кто-то заказывает пирог, создает новый пирог с уникальными ингредиентами.
Ежик: "Каждый хочет свой вкус! Поэтому я создаю свежий пирог для каждого заказа."
@Component
@Scope("prototype")
public class Hedgehog {
public void bakePie() {
System.out.println("Пеку пирог!");
}
}
Так работает scope prototype в Spring: каждый раз при запросе нового объекта создается уникальный экземпляр бина. Это полезно, когда требуется изолированная логика для каждого использования.
Например:
В приложении есть бин, который генерирует отчет для каждого пользователя:
@Component
@Scope("prototype")
public class ReportGenerator {
public Report generate(String userData) {
// Генерация уникального отчета
return new Report(userData);
}
}
Каждый вызов context.getBean(ReportGenerator.class) создаст новый экземпляр. Это удобно для обработки уникальных данных в многопользовательских системах.
Request: Кролик-раздатчик морковки
Кролик-раздатчик объясняет своим помощникам:
"Для каждого гостя, который приходит на поляну, я собираю морковку. Но как только гость уходит, корзинка возвращается ко мне."
@Component
@Scope("request")
public class Rabbit {
public void giveCarrot() {
System.out.println("Вот твоя морковка!");
}
}
Request scope в Spring означает, что один бин создается на каждый HTTP-запрос. После завершения запроса бин уничтожается.
Пример использования:
Представьте, что в веб-приложении у вас есть компонент для сбора данных пользователя:
@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserCart {
private List<Item> items = new ArrayList<>();
public void addItem(Item item) {
items.add(item);
}
public List<Item> getItems() {
return items;
}
}
Каждому запросу пользователя выделяется уникальная корзина, которая "живёт" только в рамках обработки HTTP-запроса. Как только запрос завершён, бин удаляется, освобождая память.
Сравнение Prototype и Request в реальной разработке:
Prototype: используется для задач, требующих уникальных экземпляров при каждом вызове, например, в тестировании, генерации уникальных данных, обработки изолированных задач.
Request: полезен в веб-приложениях для обеспечения изоляции данных между запросами пользователей. Например, корзина покупок, данные аутентификации или временные токены.
Разница в подходах:
Prototype может использоваться в любых контекстах, включая консольные приложения.
Request строго привязан к веб-контексту, поскольку зависит от HTTP-запросов.
Singleton: Боб-строитель
Боб-строитель работает в лесу и строит плотину для всех. Он говорит:
"Я один, и я построю что угодно, сколько бы животных ко мне ни пришло!"
Это означает, что у нас всегда будет один и тот же экземпляр объекта, к которому обращаются все клиенты. И каждый раз приходит один и тот же Боб. Ему не нужно было клонироваться или исчезать. Так он трудился день за днем.
@Component
@Scope("singleton")
public class Bob {
public void buildDam() {
System.out.println("Строю плотину!");
}
}
Singleton — это скоуп по умолчанию в Spring. Один экземпляр бина создается на всё время работы приложения. Такой бин используется, когда объект должен быть общим ресурсом для всех компонентов приложения.
Пример использования:
Предположим, у вас есть компонент для логирования:
@Component
public class Logger {
public void log(String message) {
System.out.println(message);
}
}
Этот бин создается один раз, и все компоненты приложения используют его для записи логов. Это эффективно и экономит память.
Применение:
- Логирование
- Работа с базой данных через пул соединений
- Управление кэшами
Session: Медвежонок Мед
Медвежонок варит мед для каждого гостя, который пришел в его дом. Он говорит:
"Пока ты у меня в гостях, я заботюсь о твоем горшочке. Но как только ты уходишь, твой медовый горшочек исчезает."
@Component
@Scope("session")
public class Bear {
public void makeHoney() {
System.out.println("Варю мед для тебя!");
}
}
Скоуп session в Spring означает, что бин существует столько, сколько длится HTTP-сессия пользователя.
Техническое пояснение:
Этот скоуп используется в веб-приложениях, чтобы привязать объект к конкретной сессии пользователя. Когда сессия завершается, бин уничтожается.
Пример использования:
Представьте, что у вас есть компонент для хранения данных авторизации пользователя:
@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserSession {
private String userId;
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserId() {
return userId;
}
}
Этот бин создается для каждого пользователя, пока длится его сессия.
Применение:
- Хранение данных пользователя (например, авторизации, предпочтений)
- Управление сессионными токенами
Application: Филин Фил
Филин Фил каждый вечер рассказывает сказки всем лесным жителям. Он говорит:
"Моя сказка одна на весь лес. Все приходят ко мне слушать, и всем хватает!"
@Component
@Scope("application")
public class Owl {
public void shareWisdom() {
System.out.println("Мудрость дня: бобры строят лучшие плотины.");
}
}
Скоуп application означает, что бин создается один раз на всё приложение, но отличается от singleton тем, что он используется только в контексте веб-приложений.
Этот скоуп аналогичен singleton, но управляется веб-контекстом. Он используется для компонентов, которые должны быть доступны на уровне всего приложения.
Пример использования:
Например, бин для хранения глобальных настроек:
@Component
@Scope(value = WebApplicationContext.SCOPE_APPLICATION)
public class AppSettings {
private String appName = "ForestApp";
public String getAppName() {
return appName;
}
}
Этот бин создается один раз и доступен всем.
Применение:
- Конфигурация приложения
- Глобальные настройки
- Кэш данных, общий для всех пользователей
Сравнение всех скоупов Spring
Scope | Жизненный цикл | Пример использования |
---|---|---|
Singleton | Всё время работы приложения | Логирование, работа с базами данных |
Prototype | Новый объект при каждом вызове | Генерация отчётов, тестирование |
Request | Один HTTP-запрос | Корзина покупок, временные данные |
Session | Вся HTTP-сессия пользователя | Данные авторизации, настройки пользователя |
Application | Всё время работы приложения | Глобальные настройки, кэш на уровне приложения |
Когда что использовать?
Singleton — для общих, не изменяющихся ресурсов.
Prototype — для изолированных задач, уникальных данных.
Request — для временных данных в рамках одного запроса.
Session — для данных, которые нужно хранить между запросами одного пользователя.
Application — для глобальных данных, которые используют все пользователи.
Top comments (0)