skip to content

What is the difference between BeanFactory and ApplicationContext in Spring?

level: juniorimportance: must knowfreq 85%

answer

  1. ApplicationContext = BeanFactory superset
  2. Eager singletons vs lazy lookup
  3. BPP auto-detect, events, i18n, resources
  4. DefaultListableBeanFactory is the engine
  5. Fail-fast at startup

basics

~20 s

Both are Spring IoC containers that create and wire beans. ApplicationContext is a superset of BeanFactory: it adds features like event publishing, internationalization, easy resource loading, and automatic BeanPostProcessor handling, and it eagerly creates singletons at startup.

solid answer

~30 s

BeanFactory is the root container interface — it defines core dependency injection: get a bean by name/type, check scope, resolve dependencies. It's lazy by default: a bean is only instantiated when first requested. ApplicationContext extends BeanFactory and adds an enterprise superset: ApplicationEvent publishing (ApplicationEventPublisher), MessageSource for i18n, ResourceLoader/resource-pattern support, and Environment access. Crucially, ApplicationContext auto-detects and registers BeanPostProcessors and BeanFactoryPostProcessors from bean definitions, and eagerly pre-instantiates all non-lazy singletons at startup so wiring errors surface immediately. In practice you almost always use ApplicationContext (e.g. AnnotationConfigApplicationContext, or the one Spring Boot creates). BeanFactory (DefaultListableBeanFactory) is the underlying engine ApplicationContext delegates to.

code

java · 12 lines
java
// ApplicationContext: eager, full-featured (normal choice)
try (var ctx = new AnnotationConfigApplicationContext(AppConfig.class)) {
    // all non-lazy singletons already instantiated here
    MyService svc = ctx.getBean(MyService.class);
    ctx.publishEvent(new MyEvent(this));          // events available
    ctx.getMessage("greeting", null, Locale.US);  // i18n available
}

// Raw BeanFactory: lazy, minimal — BeanPostProcessors NOT auto-applied
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions("beans.xml");
MyService svc = bf.getBean(MyService.class); // instantiated only now

go deeper

for a junior

State that both are IoC containers and ApplicationContext is a superset with extra features (events, i18n) and eager startup.

for a middle

Add the specific superset features and that ApplicationContext auto-registers BeanPostProcessors while a raw BeanFactory does not, so annotations wouldn't work.

for a senior

Explain the delegation relationship (ApplicationContext owns a DefaultListableBeanFactory), eager pre-instantiation for fail-fast, and name concrete implementations.

for a principal

Discuss lifecycle (refresh phases), when a bare BeanFactory is actually justified, memory/startup trade-offs, and how post-processors drive the whole annotation/AOP model.

## The two container interfaces Spring's Inversion of Control (IoC) container is the object that creates your objects (called **beans**), injects their dependencies, and manages their lifecycle. Spring exposes it through two main interfaces. ### BeanFactory `org.springframework.beans.factory.BeanFactory` is the **root** interface of the container hierarchy. It defines the minimal contract for dependency injection: - `Object getBean(String name)` / `<T> T getBean(Class<T> type)` — look up a bean - `boolean containsBean(String name)` - `boolean isSingleton(String name)` / `isPrototype(String name)` - `Class<?> getType(String name)` By itself, BeanFactory does the essentials: read bean definitions, instantiate, inject, apply scopes. The most-used concrete implementation is **`DefaultListableBeanFactory`** — this is the actual registry that holds `BeanDefinition` objects and performs autowiring. It's the engine inside every ApplicationContext. **Lazy by default:** a plain BeanFactory instantiates a bean only the first time `getBean` is called for it. Nothing is created up front. ### ApplicationContext `org.springframework.context.ApplicationContext` **extends** BeanFactory (transitively — via `ListableBeanFactory` and `HierarchicalBeanFactory`) and layers on enterprise features. It *is* a BeanFactory plus: - **`ApplicationEventPublisher`** — publish and listen for `ApplicationEvent`s (`@EventListener`, `publishEvent`). - **`MessageSource`** — internationalization (i18n) message resolution (`getMessage`). - **`ResourceLoader` / `ResourcePatternResolver`** — load resources with `classpath:`, `file:`, and wildcard patterns (`getResources("classpath*:...")`). - **`EnvironmentCapable`** — access to `Environment` (profiles + properties). - **Automatic infrastructure detection** — it scans bean definitions and automatically registers any `BeanPostProcessor` and `BeanFactoryPostProcessor` beans, and wires up `ApplicationContextAware`/`ApplicationEventPublisherAware` etc. - **Eager singleton pre-instantiation** — on `refresh()` it calls `finishBeanFactoryInitialization`, which pre-instantiates all non-lazy singletons so misconfiguration fails fast at startup, not at first request. ### How they relate at runtime ApplicationContext does **not** reimplement DI. It *owns* a `DefaultListableBeanFactory` internally and delegates `getBean` etc. to it. So ApplicationContext = BeanFactory engine + enterprise services + eager startup. `AbstractApplicationContext.getBeanFactory()` returns that internal DefaultListableBeanFactory. ### Common implementations - **`AnnotationConfigApplicationContext`** — Java `@Configuration` classes. - **`ClassPathXmlApplicationContext`** — XML config. - **`GenericWebApplicationContext` / `AnnotationConfigServletWebServerApplicationContext`** — web/Boot. - Boot's `SpringApplication.run(...)` returns a `ConfigurableApplicationContext`. ### Gotchas - With a **raw BeanFactory**, BeanPostProcessors are *not* auto-applied — you'd have to register them manually via `addBeanPostProcessor`. This means annotations like `@Autowired`, `@PostConstruct`, AOP proxies won't work out of the box, because they're driven by BeanPostProcessors. That's the #1 reason to never use a bare BeanFactory in application code. - Eager instantiation means a broken bean (missing dependency, bad config) throws at container startup. That's a feature: fail fast. - BeanFactory's laziness is different from `@Lazy`. A ApplicationContext is eager overall but you can mark individual beans `@Lazy` to defer them. ### When to use which Use **ApplicationContext** essentially always. Reach for BeanFactory/DefaultListableBeanFactory only in rare low-level scenarios: extremely memory-constrained environments, or when you're building infrastructure/tooling that programmatically registers bean definitions and wants full control over instantiation timing.

  • Name three capabilities ApplicationContext has that a raw BeanFactory does not.
    Automatic BeanPostProcessor/BeanFactoryPostProcessor registration, application event publishing (ApplicationEventPublisher), MessageSource-based i18n, ResourcePatternResolver for classpath wildcard resources, and Environment access. Also eager pre-instantiation of singletons.
  • Does ApplicationContext reimplement dependency injection, or reuse BeanFactory?
    It reuses it. Internally it holds a DefaultListableBeanFactory and delegates bean creation/wiring to it; ApplicationContext just adds enterprise services and eager startup on top.

saying these in an interview costs you the question

  • Saying BeanFactory and ApplicationContext are unrelated or competing containers (ApplicationContext extends BeanFactory).
  • Claiming ApplicationContext is lazy and BeanFactory is eager (it's the reverse for default singleton timing).
  • Thinking @Autowired/@PostConstruct work automatically in a raw BeanFactory (they need BeanPostProcessors, which a raw BeanFactory does not auto-register).

context