DEV Community

Cover image for Волшебные скоупы: Как Spring организует работу бинов
Olga Lugacheva
Olga Lugacheva

Posted on

Волшебные скоупы: Как Spring организует работу бинов

В мастерской Spring трудились умелые и старательные помощники — бины. Каждый из них был наделен своей уникальной задачей: кто-то создавал игрушки, кто-то сортировал конфеты, а кто-то выращивал яркие цветы.

Чтобы работа мастерской была упорядоченной и эффективной, для бинов были установлены четкие правила — скоупы. Эти правила определяли, как долго бины могли существовать и сколько экземпляров одного вида должно быть создано одновременно. Благодаря этим волшебным рамкам мастерская работала слаженно и надежно.

Прототип (Prototype): Ежик-пекарь

hedgehog
Ежик-пекарь каждый раз, когда кто-то заказывает пирог, создает новый пирог с уникальными ингредиентами.

Ежик: "Каждый хочет свой вкус! Поэтому я создаю свежий пирог для каждого заказа."

@Component
@Scope("prototype")
public class Hedgehog {
    public void bakePie() {
        System.out.println("Пеку пирог!");
    }
}

Enter fullscreen mode Exit fullscreen mode

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

Например:

В приложении есть бин, который генерирует отчет для каждого пользователя:

@Component
@Scope("prototype")
public class ReportGenerator {
    public Report generate(String userData) {
        // Генерация уникального отчета
        return new Report(userData);
    }
}

Enter fullscreen mode Exit fullscreen mode

Каждый вызов context.getBean(ReportGenerator.class) создаст новый экземпляр. Это удобно для обработки уникальных данных в многопользовательских системах.


Request: Кролик-раздатчик морковки

rbt
Кролик-раздатчик объясняет своим помощникам:

"Для каждого гостя, который приходит на поляну, я собираю морковку. Но как только гость уходит, корзинка возвращается ко мне."

@Component
@Scope("request")
public class Rabbit {
    public void giveCarrot() {
        System.out.println("Вот твоя морковка!");
    }
}

Enter fullscreen mode Exit fullscreen mode

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;
    }
}

Enter fullscreen mode Exit fullscreen mode

Каждому запросу пользователя выделяется уникальная корзина, которая "живёт" только в рамках обработки HTTP-запроса. Как только запрос завершён, бин удаляется, освобождая память.

Сравнение Prototype и Request в реальной разработке:

Prototype: используется для задач, требующих уникальных экземпляров при каждом вызове, например, в тестировании, генерации уникальных данных, обработки изолированных задач.
Request: полезен в веб-приложениях для обеспечения изоляции данных между запросами пользователей. Например, корзина покупок, данные аутентификации или временные токены.
Разница в подходах:

Prototype может использоваться в любых контекстах, включая консольные приложения.
Request строго привязан к веб-контексту, поскольку зависит от HTTP-запросов.


Singleton: Боб-строитель

woodchuck
Боб-строитель работает в лесу и строит плотину для всех. Он говорит:

"Я один, и я построю что угодно, сколько бы животных ко мне ни пришло!"

Это означает, что у нас всегда будет один и тот же экземпляр объекта, к которому обращаются все клиенты. И каждый раз приходит один и тот же Боб. Ему не нужно было клонироваться или исчезать. Так он трудился день за днем.

@Component
@Scope("singleton")
public class Bob {
    public void buildDam() {
        System.out.println("Строю плотину!");
    }
}

Enter fullscreen mode Exit fullscreen mode

Singleton — это скоуп по умолчанию в Spring. Один экземпляр бина создается на всё время работы приложения. Такой бин используется, когда объект должен быть общим ресурсом для всех компонентов приложения.

Пример использования:
Предположим, у вас есть компонент для логирования:

@Component
public class Logger {
    public void log(String message) {
        System.out.println(message);
    }
}

Enter fullscreen mode Exit fullscreen mode

Этот бин создается один раз, и все компоненты приложения используют его для записи логов. Это эффективно и экономит память.

Применение:

  • Логирование
  • Работа с базой данных через пул соединений
  • Управление кэшами

Session: Медвежонок Мед

bear
Медвежонок варит мед для каждого гостя, который пришел в его дом. Он говорит:

"Пока ты у меня в гостях, я заботюсь о твоем горшочке. Но как только ты уходишь, твой медовый горшочек исчезает."

@Component
@Scope("session")
public class Bear {
    public void makeHoney() {
        System.out.println("Варю мед для тебя!");
    }
}

Enter fullscreen mode Exit fullscreen mode

Скоуп 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;
    }
}

Enter fullscreen mode Exit fullscreen mode

Этот бин создается для каждого пользователя, пока длится его сессия.

Применение:

  • Хранение данных пользователя (например, авторизации, предпочтений)
  • Управление сессионными токенами

Application: Филин Фил

Филин Фил каждый вечер рассказывает сказки всем лесным жителям. Он говорит:

"Моя сказка одна на весь лес. Все приходят ко мне слушать, и всем хватает!"

@Component
@Scope("application")
public class Owl {
    public void shareWisdom() {
        System.out.println("Мудрость дня: бобры строят лучшие плотины.");
    }
}

Enter fullscreen mode Exit fullscreen mode

Скоуп application означает, что бин создается один раз на всё приложение, но отличается от singleton тем, что он используется только в контексте веб-приложений.

Этот скоуп аналогичен singleton, но управляется веб-контекстом. Он используется для компонентов, которые должны быть доступны на уровне всего приложения.

Пример использования:
Например, бин для хранения глобальных настроек:

@Component
@Scope(value = WebApplicationContext.SCOPE_APPLICATION)
public class AppSettings {
    private String appName = "ForestApp";

    public String getAppName() {
        return appName;
    }
}

Enter fullscreen mode Exit fullscreen mode

Этот бин создается один раз и доступен всем.

Применение:

  • Конфигурация приложения
  • Глобальные настройки
  • Кэш данных, общий для всех пользователей

Сравнение всех скоупов Spring

Scope Жизненный цикл Пример использования
Singleton Всё время работы приложения Логирование, работа с базами данных
Prototype Новый объект при каждом вызове Генерация отчётов, тестирование
Request Один HTTP-запрос Корзина покупок, временные данные
Session Вся HTTP-сессия пользователя Данные авторизации, настройки пользователя
Application Всё время работы приложения Глобальные настройки, кэш на уровне приложения

Когда что использовать?
Singleton — для общих, не изменяющихся ресурсов.
Prototype — для изолированных задач, уникальных данных.
Request — для временных данных в рамках одного запроса.
Session — для данных, которые нужно хранить между запросами одного пользователя.
Application — для глобальных данных, которые используют все пользователи.

Top comments (0)