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

Кто создает Bean в Spring

1.0 Junior🔥 151 комментариев
#Spring Framework

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

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

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

Кто создаёт Bean в Spring

В Spring IoC контейнере есть иерархия компонентов, которые отвечают за создание и управление бинами. Это не просто волшебство — есть чёткая архитектура.

Главные игроки

1. BeanFactory — базовая фабрика

BeanFactory — это самый низкий уровень, основной интерфейс для создания и получения бинов:

public interface BeanFactory {
  Object getBean(String name);
  <T> T getBean(String name, Class<T> requiredType);
  <T> T getBean(Class<T> requiredType);
  boolean containsBean(String name);
  boolean isSingleton(String name);
  Class<?> getType(String name);
}

Это ленивая фабрика — бины создаются только когда их запрашивают.

2. ApplicationContext — расширенный контейнер

ApplicationContext расширяет BeanFactory и добавляет много функциональности:

public interface ApplicationContext extends BeanFactory, ResourceLoader, EnvironmentCapable {
  // Все методы BeanFactory
  // Плюс дополнительные возможности
  String getDisplayName();
  long getStartupDate();
  void refresh() throws BeansException;
}

Он создаёт все бины при старте (eager initialization).

3. BeanDefinition — описание бина

Кажды бин описывается BeanDefinition:

public interface BeanDefinition {
  String SCOPE_SINGLETON = "singleton";
  String SCOPE_PROTOTYPE = "prototype";
  
  // Методы для получения информации о бине
  String getBeanClassName();
  String getFactoryBeanName();
  String getFactoryMethodName();
  String getScope();
  boolean isSingleton();
  boolean isPrototype();
  Constructor<?>[] getConstructors();
  // ... и ещё много
}

Это полный blueprint того, как нужно создавать бин.

4. BeanDefinitionRegistry — регистр определений

Хранит все BeanDefinition:

public interface BeanDefinitionRegistry {
  void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
  void removeBeanDefinition(String beanName);
  BeanDefinition getBeanDefinition(String beanName);
  boolean containsBeanDefinition(String beanName);
  String[] getBeanDefinitionNames();
  int getBeanDefinitionCount();
}

Процесс создания Bean

Этап 1: Сканирование и регистрация (Registration)

Spring сканирует classpath и создаёт BeanDefinition для каждого найденного класса:

// 1. Spring находит @Component, @Service, @Repository, @Controller
@Component
public class UserService {
  // ...
}

// 2. Создаёт BeanDefinition
BeanDefinition bd = new GenericBeanDefinition();
bd.setBeanClass(UserService.class);
bd.setScope("singleton");

// 3. Регистрирует в BeanDefinitionRegistry
beanDefinitionRegistry.registerBeanDefinition("userService", bd);

Или для @Bean методов:

@Configuration
public class AppConfig {
  @Bean
  public UserService userService() {
    return new UserService();
  }
}

// Spring создаёт BeanDefinition с factoryMethod="userService"

Этап 2: Инстанцирование (Instantiation)

Главный интерфейс — BeanFactory:

public class SimpleBeanFactory implements BeanFactory {
  private Map<String, Object> singletons = new HashMap<>();
  private Map<String, BeanDefinition> definitions = new HashMap<>();
  
  public Object getBean(String name) {
    // Шаг 1: Проверяем, есть ли уже созданный синглтон
    if (singletons.containsKey(name)) {
      return singletons.get(name);
    }
    
    // Шаг 2: Получаем определение
    BeanDefinition bd = definitions.get(name);
    
    // Шаг 3: Инстанцируем через конструктор
    Object instance = instantiate(bd);
    
    // Шаг 4: Инжектируем зависимости
    autowire(instance, bd);
    
    // Шаг 5: Вызываем инициализацию
    initialize(instance, bd);
    
    // Шаг 6: Сохраняем синглтон
    singletons.put(name, instance);
    
    return instance;
  }
}

Этап 3: Инъекция зависимостей (Dependency Injection)

Это делает AutowireCapableBeanFactory:

public interface AutowireCapableBeanFactory {
  // Три способа autowiring
  int AUTOWIRE_NO = 0;            // Без автоматической инъекции
  int AUTOWIRE_BY_NAME = 1;       // По имени поля
  int AUTOWIRE_BY_TYPE = 2;       // По типу
  int AUTOWIRE_CONSTRUCTOR = 3;   // Через конструктор
  
  Object createBean(Class<?> beanClass);
  void autowireBean(Object existingBean);
}

Пример автоматической инъекции:

@Component
public class UserService {
  private UserRepository repository;  // Помечено @Autowired
  
  @Autowired
  public UserService(UserRepository repository) {
    this.repository = repository;  // Spring автоматически найдёт и инжектит
  }
}

Этап 4: Инициализация (Initialization)

Вызываются callback-методы:

@Component
public class DataSource {
  @PostConstruct
  public void init() {
    System.out.println("Initializing DataSource");
    // Подключение к БД, загрузка конфигурации, etc.
  }
}

Главные классы Spring

DefaultListableBeanFactory — основная реализация:

// Это класс, который на 90% отвечает за создание бинов
public class DefaultListableBeanFactory 
  extends AbstractAutowireCapableBeanFactory
  implements ConfigurableListableBeanFactory,
             BeanDefinitionRegistry {
  
  private Map<String, BeanDefinition> beanDefinitions;
  private Map<String, Object> singletonObjects;
  
  // Все методы для регистрации и получения бинов
}

AbstractAutowireCapableBeanFactory — логика инъекции:

public abstract class AbstractAutowireCapableBeanFactory {
  // Логика autowiring по типу
  protected void populateBean(String beanName, 
                               BeanDefinition mbd, 
                               BeanWrapper bw) {
    // Ищем все @Autowired поля и методы
    // Создаём нужные бины
    // Инжектируем их
  }
}

ConfigurableApplicationContext — управление жизненным циклом:

public interface ConfigurableApplicationContext extends ApplicationContext {
  void refresh() throws BeansException;  // Перезагрузить все бины
  void close();  // Остановить контейнер и вызвать @PreDestroy
  boolean isActive();  // Работает ли контейнер
  void registerShutdownHook();  // Регистр при выключении JVM
}

Полный жизненный цикл

1. Spring стартует
   ↓
2. Сканирует classpath (@ComponentScan)
   ↓
3. Находит @Component, @Service, @Bean, etc.
   ↓
4. Создаёт BeanDefinition для каждого
   ↓
5. Регистрирует в BeanDefinitionRegistry
   ↓
6. Начинает инстанцирование (в порядке зависимостей)
   ├─ Вызывает конструктор
   ├─ Autowiring (инжекция зависимостей)
   ├─ @PostConstruct методы
   └─ Готово к использованию
   ↓
7. При выключении приложения
   ├─ Вызывает @PreDestroy методы
   └─ Закрывает ресурсы

Реальный пример из Spring

public class Main {
  public static void main(String[] args) {
    // Это создаёт ApplicationContext
    ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
    
    // Это вызывает BeanFactory.getBean()
    UserService userService = ctx.getBean(UserService.class);
    
    // Spring уже создал все бины, инжектил зависимости
    // вызвал @PostConstruct, и теперь можно использовать
    userService.createUser("John");
    
    // При завершении программы
    ((ConfigurableApplicationContext) ctx).close();
    // Spring вызовет все @PreDestroy методы
  }
}

Итоговая схема

ApplicationContext (главный контейнер)
  ↓
BeanDefinitionRegistry (хранилище определений)
  ↓
DefaultListableBeanFactory (основная фабрика)
  ├─ BeanFactory (создание бинов)
  ├─ AutowireCapableBeanFactory (инъекция)
  └─ ObjectProvider (поиск бинов)

Короче: Spring ApplicationContext это главный ответственный, DefaultListableBeanFactory это рабочая лошадка, которая всё делает на практике.

Кто создает Bean в Spring | PrepBro