Где хранится Singleton бин?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
# Где хранится Singleton бин в Spring?
Основной ответ
Singleton бины хранятся в Spring контейнере (ApplicationContext) в специальной кэш-структуре. В частности, для singleton scope используются две основные карты:
// DefaultSingletonBeanRegistry.java (часть Spring Framework)
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
private final Map<String, ObjectFactory<?>> singletonFactories =
new LinkedHashMap<>();
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>();
Детали хранения
1. Главная карта - singletonObjects
Это основное место, где хранятся полностью инициализированные singleton бины:
// Когда бин создан и инициализирован, он попадает сюда
singletonObjects.put(beanName, beanInstance);
2. singletonFactories - фабрики объектов
Вспомогательная карта для разрешения циклических зависимостей (circular dependencies):
// На ранних стадиях создания бина
singletonFactories.put(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
3. earlySingletonObjects - ранние синглтоны
Кэш для частично инициализированных бинов (для circular dependencies):
// При обнаружении циклической зависимости
earlySingletonObjects.put(beanName, singletonFactory.getObject());
Жизненный цикл Singleton бина
@Configuration
public class AppConfig {
@Bean
public UserService userService() {
return new UserService(); // Этот объект создаётся один раз
}
}
// Когда ApplicationContext инициализируется:
// 1. Создаёт экземпляр UserService
// 2. Вызывает @PostConstruct методы
// 3. Сохраняет в singletonObjects с ключом "userService"
// 4. При каждом обращении - возвращает тот же объект
Как получить доступ к синглтонам
// Через ApplicationContext
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService service = context.getBean(UserService.class);
// Все последующие вызовы вернут ТОТ ЖЕ объект
UserService service2 = context.getBean(UserService.class);
assert service == service2; // true - один и тот же экземпляр
Важные моменты
Thread Safety
Spring использует ConcurrentHashMap для thread-safe доступа:
// Потокобезопасно - несколько потоков могут одновременно получать бин
UserService s1 = context.getBean(UserService.class);
UserService s2 = context.getBean(UserService.class);
Другие scope бинов
// Prototype - новый объект каждый раз
@Bean
@Scope("prototype")
public UserService userService() { ... }
// Request - один объект на HTTP запрос
@Bean
@Scope("request")
public RequestData data() { ... }
// Session - один объект на сессию
@Bean
@Scope("session")
public SessionData data() { ... }
Внутренняя структура
// Просмотр всех синглтонов (для отладки)
if (context instanceof DefaultListableBeanFactory) {
DefaultListableBeanFactory factory =
(DefaultListableBeanFactory) context;
String[] singletonNames = factory.getSingletonNames();
for (String name : singletonNames) {
System.out.println(name); // Имена всех singleton бинов
}
}
Заключение
Singleton бины хранятся в памяти приложения в контейнере Spring (ApplicationContext) в виде ConcurrentHashMap для обеспечения потокобезопасности и быстрого доступа. Это позволяет Spring гарантировать, что один и тот же экземпляр бина используется во всём приложении, что повышает производительность и позволяет управлять состоянием объектов.