← Назад к вопросам

Какой по-умолчанию scope у бинов?

2.0 Middle🔥 111 комментариев
#Spring Framework

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Scope бинов в Spring Framework

В Spring Framework по умолчанию используется singleton scope. Это означает, что один bean создаётся один раз на всё время жизни приложения и переиспользуется во все местах.

Singleton (по умолчанию)

Singleton scope — это scope по умолчанию. Spring создаёт один экземпляр bean и повторно использует его для всех запросов.

// Явное указание Singleton (по умолчанию)
@Bean
@Scope("singleton")
public UserService userService() {
    return new UserService();
}

// Или просто (по умолчанию — singleton)
@Bean
public UserService userService() {
    return new UserService();
}

// Проверка: оба экземпляра будут одинаковые
UserService service1 = context.getBean(UserService.class);
UserService service2 = context.getBean(UserService.class);
System.out.println(service1 == service2); // true

Характеристики Singleton:

  • Один экземпляр на всё приложение
  • Инстанцирование при старте приложения
  • Потокобезопасность требует синхронизации
  • Экономит память
  • Идеален для stateless объектов (сервисов)

Prototype

Prototype scope — для каждого запроса создаётся новый экземпляр bean.

@Bean
@Scope("prototype")
public RequestData requestData() {
    return new RequestData();
}

// Проверка: экземпляры будут разные
RequestData data1 = context.getBean(RequestData.class);
RequestData data2 = context.getBean(RequestData.class);
System.out.println(data1 == data2); // false

Характеристики Prototype:

  • Новый экземпляр при каждом запросе
  • Инстанцирование при запросе bean
  • Потокобезопасен по природе
  • Больше памяти
  • Идеален для stateful объектов

Веб-приложение: Request Scope

Request scope используется в веб-приложениях. Bean живёт во время одного HTTP запроса.

@Component
@Scope("request")
public RequestContext requestContext() {
    return new RequestContext();
}

// В контроллере
@RestController
public class UserController {
    @Autowired
    private RequestContext requestContext;
    
    @GetMapping("/users/{id}")
    public User getUser(@PathVariable Long id) {
        // requestContext существует только во время этого запроса
        return userService.findById(id);
    }
}

Характеристики Request Scope:

  • Один bean на HTTP запрос
  • Создание при начале запроса
  • Уничтожение в конце запроса
  • Идеален для хранения данных запроса
  • Требует Web контекст (ServletContext)

Session Scope

Session scope — bean живёт во время сессии пользователя.

@Component
@Scope("session")
public UserSession userSession() {
    return new UserSession();
}

// В контроллере
@RestController
public class ProfileController {
    @Autowired
    private UserSession userSession;
    
    @GetMapping("/profile")
    public UserInfo getProfile() {
        // userSession существует для каждой сессии
        return userSession.getCurrentUser();
    }
}

Характеристики Session Scope:

  • Один bean на пользовательскую сессию
  • Создание при первом обращении в сессии
  • Уничтожение при завершении сессии
  • Хранит данные пользователя
  • Требует Web контекст

Application Scope

Application scope — один bean на приложение в веб-контексте (как servlet scope).

@Component
@Scope(WebApplicationContext.SCOPE_APPLICATION)
public AppConfig appConfig() {
    return new AppConfig();
}

Это похоже на singleton, но специфично для веб-контекста.

Custom Scope

Можно создать свой scope.

@Configuration
public class CustomScopeConfig {
    @Bean
    public CustomScope customScope() {
        return new CustomScope();
    }
    
    @Bean
    public static CustomScopeConfigurer customScopeConfigurer() {
        CustomScopeConfigurer configurer = new CustomScopeConfigurer();
        configurer.addScope("custom", customScope());
        return configurer;
    }
}

// Использование
@Component
@Scope("custom")
public MyBean myBean() {
    return new MyBean();
}

ScopedProxyMode

Для внедрения shorter-lived bean в longer-lived bean используется proxy:

@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public RequestData requestData() {
    return new RequestData();
}

// Singleton сервис может внедрить request-scoped bean
@Service
public class MyService {
    @Autowired
    private RequestData requestData; // Proxy к request bean
}

Таблица Scopes

ScopeЖизненный циклКоличествоИспользование
SingletonПриложение1 на приложениеСервисы, репозитории
PrototypeЗапросНовый каждый разStateful объекты
RequestHTTP запрос1 на запросКонтекст запроса
SessionПользовательская сессия1 на сессиюДанные пользователя
ApplicationПриложение (веб)1 на приложениеКонфигурация

Примеры использования

Singleton (по умолчанию) — сервис

@Service
public class UserService {
    // Автоматически Singleton
    // Безопасен, если нет состояния
    
    public User findById(Long id) {
        // Статические методы или доступ к БД
        return userRepository.findById(id).orElse(null);
    }
}

Prototype — для временных объектов

@Component
@Scope("prototype")
public DataProcessor {
    private List<String> buffer = new ArrayList<>();
    
    // Новый экземпляр каждый раз, состояние изолировано
    public void process(String data) {
        buffer.add(data);
    }
}

Request — для контекста запроса

@Component
@Scope("request")
public HttpContext {
    private String userId;
    private String requestId;
    
    // Данные только для этого запроса
}

Лучшие практики

  1. По умолчанию используйте Singleton — большинство бинов должны быть stateless
  2. Prototype только если нужно — для действительно stateful объектов
  3. Request scope в веб-приложениях — для изоляции данных запроса
  4. Избегайте состояния в Singleton — используйте параметры методов
  5. Используйте proxy для混合 scopes — когда shorter-lived внедрять в longer-lived

Проверка scope bean

ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
BeanDefinition definition = beanFactory.getBeanDefinition("myBean");
String scope = definition.getScope();
System.out.println("Bean scope: " + scope); // singleton, prototype и т.д.

Вывод: По умолчанию Spring использует Singleton scope для всех бинов. Это означает, что один экземпляр bean создаётся один раз при запуске приложения и переиспользуется везде. Это оптимально для stateless сервисов и экономит память. Для других случаев доступны Prototype, Request, Session и другие scopes.