Какой scope у бина, объявленного с аннотацией @Component, если не указан явно?

Ответ

Бин, объявленный с помощью @Component (или ее специализаций: @Service, @Repository, @Controller), по умолчанию имеет scope singleton.

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

Пример:

@Component // Неявно @Scope("singleton")
public class ShoppingCartService {
    private List<Item> items = new ArrayList<>();
    // Это поле будет общим для всех клиентов, использующих этот бин,
    // что обычно является ошибкой дизайна для такого сервиса.
}

Как проверить или изменить:

  1. Проверить: Можно инжектировать бин в два разных места и сравнить ссылки (==). Они будут одинаковыми.
  2. Изменить: Явно указать другую область видимости с помощью аннотации @Scope.
    @Component
    @Scope("prototype") // Теперь при каждом инжекте будет новый экземпляр
    public class PrototypeComponent { }

Важно: Для stateful-бинов, хранящих данные конкретного пользователя или запроса (как ShoppingCartService в примере), singleton scope не подходит. В таких случаях следует использовать request или session scope, либо полностью избегать хранения состояния в бине.

Ответ 18+ 🔞

А, слушай, вот это прикол! Ты знаешь, как эти ваши @Component и @Service там по умолчанию живут? Они же, блядь, как одинокий волк в лесу — один на весь контейнер! Scope singleton, ёпта!

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

Смотри, пример, где всё наебнётся:

@Component // Тут по умолчанию @Scope("singleton"), но все про это забывают, как про вчерашнее похмелье
public class ShoppingCartService {
    private List<Item> items = new ArrayList<>(); // А вот это поле — общая помойка для всех!
    // Представь: Вася положил телевизор, а Петя пришёл и видит его в своей корзине. Пиздец и скандал.
}

Что делать, если охуел от такого поведения:

  1. Проверить, не глючит ли: Заинжекти этот бин в двух разных местах и сравни через ==. Если true — ну всё, поздравляю, это один и тот же объект, синглтон, блядь.
  2. Изменить, если надо: Въеби явную аннотацию @Scope, чтобы Spring не выёбывался.
    @Component
    @Scope("prototype") // Теперь, сука, при каждом обращении будет новый, свеженький экземпляр. Как одноразовые стаканчики.
    public class PrototypeComponent { }

Важный момент, на котором все обжигаются: Если твой бин хранит состояние (какую-то хуйню в полях), как тот сервис корзины, то делать его синглтоном — это прям пиздецовая идея. Это как одной зубной щёткой на весь подъезд. Для таких случаев нужны scope request или session, либо вообще перестать хранить состояние в бине, а то волнение ебать!