Spring FrameworkMiddleTechnical

В чём разница между BeanFactory и ApplicationContext?

BeanFactory — базовый IoC-контейнер с ленивой инициализацией без автообнаружения постпроцессоров. ApplicationContext расширяет его: eager-инициализация singleton-бинов, события, i18n, Environment/profiles — в реальных проектах всегда используют ApplicationContext.

BeanFactory vs ApplicationContext

BeanFactory — это базовый контейнер IoC из пакета org.springframework.beans.factory. Он поддерживает только ленивую инициализацию бинов и базовый dependency injection. ApplicationContext расширяет BeanFactory и добавляет инфраструктурные возможности: публикацию событий через ApplicationEventPublisher, интернационализацию через MessageSource, интеграцию с AOP, автоматическое обнаружение BeanPostProcessor и BeanFactoryPostProcessor, а также поддержку eager-инициализации singleton-бинов при старте.

Ключевые отличия

  • Инициализация бинов: BeanFactory создаёт бины лениво (при первом getBean()); ApplicationContext по умолчанию инициализирует все singleton-бины при старте контекста — ошибки конфигурации обнаруживаются сразу.
  • Автообнаружение постпроцессоров: В BeanFactory нужно вручную регистрировать BeanPostProcessor; ApplicationContext сканирует контейнер автоматически.
  • События: Только ApplicationContext поддерживает ApplicationEvent / @EventListener.
  • MessageSource / i18n: Встроен только в ApplicationContext.
  • Environment и PropertySources: Абстракция Environment (profiles, properties) доступна через ApplicationContext.

Пример: ручное использование BeanFactory

// Низкоуровневый подход — крайне редко нужен в реальных проектах
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(new ClassPathResource("beans.xml"));

// BeanPostProcessor-ы НЕ применяются автоматически!
factory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());

MyService service = factory.getBean(MyService.class);

Пример: стандартный ApplicationContext

// В Spring Boot это делается автоматически через SpringApplication.run()
@SpringBootApplication
public class App {
    public static void main(String[] args) {
        ConfigurableApplicationContext ctx = SpringApplication.run(App.class, args);

        // Публикация события
        ctx.publishEvent(new UserRegisteredEvent(ctx, userId));

        // i18n
        String msg = ctx.getMessage("welcome.message", null, Locale.ENGLISH);
    }
}

// Получение Environment для работы с профилями
@Component
public class FeatureToggle {
    @Autowired
    private Environment env;

    public boolean isPremiumEnabled() {
        return env.acceptsProfiles(Profiles.of("premium"));
    }
}

Когда использовать BeanFactory

BeanFactory применяется в крайне ограниченных сценариях: встраиваемые системы с очень ограниченной памятью, тесты с изоляцией на уровне контейнера, или плагинные системы, где нужен полный контроль над жизненным циклом. В 99% случаев правильный выбор — ApplicationContext.

Подводные камни

  • При использовании BeanFactory напрямую @Autowired, @Value и @PostConstruct не работают без явной регистрации AutowiredAnnotationBeanPostProcessor и CommonAnnotationBeanPostProcessor.
  • BeanFactory не вызывает destroy-методы (@PreDestroy, DisposableBean) автоматически — нужно явно вызывать destroySingletons().
  • Ленивая инициализация в BeanFactory маскирует ошибки конфигурации до первого использования бина в рантайме.
  • Попытка инжектировать ApplicationContext-специфичные абстракции (например, ApplicationEventPublisher) в контекст, созданный как BeanFactory, приведёт к NoSuchBeanDefinitionException.
  • Иерархия контекстов (parent/child ApplicationContext в Spring MVC) — бин из дочернего контекста не виден в родительском, но видит родительский. Это частый источник ошибок с транзакциями.
  • Профили (@Profile) работают только через Environment в ApplicationContext; в bare BeanFactory профили не применяются.
  • Не путать BeanFactory с FactoryBean — последний является бином, который сам создаёт другие объекты (паттерн Factory).

Common mistakes

  • Путать термин «beanfactory applicationcontext» с соседним механизмом Spring Framework.
  • Не называть границу lifecycle, transaction, thread или request для «beanfactory applicationcontext».
  • Игнорировать production-эффекты «beanfactory applicationcontext»: latency, SQL shape, memory, security или observability.

What the interviewer is testing

  • Попросить объяснить механизм «beanfactory applicationcontext» на минимальном примере.
  • Проверить, видит ли кандидат failure mode и диагностику для «beanfactory applicationcontext».
  • Уточнить, какие настройки или API меняют «beanfactory applicationcontext» в реальном сервисе.

Sources

Related topics