← Назад к вопросам
Будут ли созданы два разных экземпляра бина, если два класса используют один и тот же бин
1.8 Middle🔥 201 комментариев
#Spring Boot и Spring Data#Spring Framework
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Создание экземпляров Spring бинов при совместном использовании
Нет, не будут созданы два разных экземпляра. Spring создаст ровно один экземпляр бина и внедрит его обоим классам. Это называется Singleton паттерн — дефолтное поведение Spring контейнера.
Singleton Scope (по умолчанию)
@Configuration
public class AppConfig {
@Bean
public UserService userService() {
return new UserService();
}
}
@Component
public class OrderController {
@Autowired
private UserService userService; // Получит ОДИН экземпляр
}
@Component
public class PaymentService {
@Autowired
private UserService userService; // ТОТ ЖЕ экземпляр, что выше
}
Оба класса получат ссылку на один и тот же объект UserService. Это подтвердить через equals и hashCode:
public class BeanSingletonTest {
@Test
public void testBeanIsSingleton(ApplicationContext context) {
UserService service1 = context.getBean(UserService.class);
UserService service2 = context.getBean(UserService.class);
assertTrue(service1 == service2); // Один и тот же объект в памяти
}
}
Когда нужны разные экземпляры
Если нужны разные экземпляры, используй scope "prototype":
@Component
@Scope("prototype")
public class UserService {
// ...
}
Теперь каждый вызов getBean() или @Autowired создаст новый экземпляр:
@Test
public void testBeanIsPrototype(ApplicationContext context) {
UserService service1 = context.getBean(UserService.class);
UserService service2 = context.getBean(UserService.class);
assertFalse(service1 == service2); // Разные объекты
}
Другие Scopes
- singleton (по умолчанию) — один экземпляр на всё приложение
- prototype — новый экземпляр каждый раз
- request (в web приложениях) — новый для каждого HTTP запроса
- session (в web приложениях) — новый для каждой пользовательской сессии
- application — один на весь ServletContext
- websocket — один на WebSocket сессию
Практическое применение
В моём опыте singleton использовался для:
- Stateless сервисов (UserService, OrderService)
- Компонентов с дорогостоящей инициализацией
- Репозиториев и DAO
Prototype использовался для:
- Объектов с состоянием, специфичным для одного использования
- Event объектов
- Временных контейнеров данных
Важные нюансы
- Thread Safety — Singleton должны быть thread-safe, так как используются одновременно разными потоками
- Lazy Initialization — Singleton создаются при первом обращении (если не указано иное)
- Circular Dependencies — с prototype сложнее решать циклические зависимости
Проверка типа скопа
public class BeanScopeChecker implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext context) {
ConfigurableApplicationContext appContext = (ConfigurableApplicationContext) context;
ConfigurableBeanFactory factory = appContext.getBeanFactory();
String scope = factory.getBeanDefinition("userService").getScope();
System.out.println("Scope: " + scope); // singleton или prototype
}
}
Итак, при совместном использовании одного бина двумя классами Spring гарантирует, что оба получат ссылку на один и тот же singleton экземпляр, если явно не указано другое через @Scope("prototype").