skip to content

Container & Bean Definitions

How Spring represents and holds beans: the BeanFactory versus ApplicationContext split, BeanDefinition metadata, context startup, and FactoryBean-style indirect creation. This is the layer that explains what actually happens between your annotation and a live object.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

26

What is a BeanDefinition in Spring, and what information does it hold?

level: juniorimportance: must knowfreq 70%

answer

  1. recipe not the dish
  2. class + scope + lazy + primary + values
  3. stored in BeanDefinitionRegistry
  4. define → post-process → instantiate
  5. one per bean regardless of source

basics

~20 s

A BeanDefinition is Spring's recipe for a bean: it stores metadata like the class name, scope, whether it's lazy, its constructor arguments and property values, and dependencies — the container reads it to create the actual bean instance.

solid answer

~30 s

A BeanDefinition is the metadata object describing how the container should create and configure one bean — it is not the bean instance itself. It holds the bean class (or factory-method), scope (singleton/prototype), lazy-init flag, primary flag, autowire mode, constructor argument values, property values, init/destroy method names, and dependency info. Whether you use XML, @Component scanning, or @Bean methods, everything is normalized into BeanDefinition objects stored in a BeanDefinitionRegistry. During refresh, BeanFactoryPostProcessors can still mutate these definitions; only afterwards does the factory instantiate beans from them. So BeanDefinition is the design-time 'recipe', and the bean is the runtime 'dish'.

code

java · 9 lines
java
// Inspecting a registered BeanDefinition (e.g., inside a BeanFactoryPostProcessor)
ConfigurableListableBeanFactory bf = context.getBeanFactory();
BeanDefinition def = bf.getBeanDefinition("orderService");

System.out.println(def.getBeanClassName()); // e.g. com.acme.OrderService (may be null for @Bean methods)
System.out.println(def.getScope());         // "singleton"
System.out.println(def.isLazyInit());       // false
System.out.println(def.isPrimary());        // false
// No bean instance exists yet at this point — this is only the metadata.

go deeper

for a junior

Know it's the 'recipe' for a bean holding class, scope, and dependency info, distinct from the instance.

for a middle

List concrete fields (scope, lazy, primary, constructor args, property values) and that all config sources normalize into it.

for a senior

Explain the define→post-process→instantiate phasing and how BeanFactoryPostProcessors mutate definitions before instantiation.

for a principal

Discuss role hints, abstract/parent templates, factory-method vs class name, and how the metadata model underpins profiles, proxying, and tooling.

## What it is A `BeanDefinition` (interface `org.springframework.beans.factory.config.BeanDefinition`) is Spring's **in-memory description of a bean** — the configuration metadata the container needs to instantiate, configure, and manage a single bean. Crucially, it is **not the bean object itself**: it is the *recipe*, while the bean is the *cooked dish*. No matter the configuration source — XML `<bean>` elements, annotation scanning of `@Component`/`@Service`, or `@Bean` factory methods in a `@Configuration` class — Spring parses each into a `BeanDefinition` and registers it in a `BeanDefinitionRegistry` (which `DefaultListableBeanFactory` implements). Instantiation of the real beans happens **later**, during `AbstractApplicationContext.refresh()`, after all definitions are registered and post-processed. ## What a BeanDefinition holds - **`beanClassName`** — the fully-qualified class to instantiate (or `factoryBeanName` + `factoryMethodName` for `@Bean` methods). - **`scope`** — `singleton` (default), `prototype`, or a web/custom scope name. - **`lazyInit`** — if `true`, a singleton is not created eagerly at startup but on first request. - **`primary`** — marks this as the preferred candidate when multiple beans of a type exist for autowiring. - **`autowireMode`** — legacy XML autowiring mode (`no`, `byName`, `byType`, `constructor`). - **`constructorArgumentValues`** and **`propertyValues` (MutablePropertyValues)** — values/refs to inject. - **`initMethodName` / `destroyMethodName`** — lifecycle callbacks. - **`dependsOn`** — names of beans that must be created first. - **`role`** — `ROLE_APPLICATION`, `ROLE_SUPPORT`, or `ROLE_INFRASTRUCTURE` (a hint about who owns it). - **`abstract`** — if `true`, it is a template not instantiated on its own (parent for child definitions). ## Why this indirection matters Because configuration is captured as data **before** any bean is created, Spring can transform it. `BeanFactoryPostProcessor`s (e.g. `PropertySourcesPlaceholderConfigurer`) run against the raw definitions and can rewrite property values or scopes. Only after that pass does the factory begin instantiation. This two-phase model (define → post-process → instantiate) is the reason profiles, placeholders, and proxying work. ## Gotchas - A `BeanDefinition` does **not** by itself represent an instance; asking `getBean` triggers creation from it. - `getBeanClassName()` can be `null` for `@Bean`-style definitions that use a factory method instead of a direct class. - Editing a definition after the factory has been frozen/refreshed is not allowed for singletons already created. ## When to touch it directly Mostly you don't — annotations/XML suffice. You reach for the API when writing infrastructure: a `BeanFactoryPostProcessor` tweaking scopes, tooling that inspects the container, or programmatic registration via `BeanDefinitionBuilder`.

  • Is a BeanDefinition the same as the bean instance?
    No. The BeanDefinition is the metadata/recipe; the bean instance is created later by the factory from that recipe. One definition can produce many prototype instances or a single shared singleton.
  • Why does Spring normalize XML, annotations, and @Bean methods all into BeanDefinitions?
    So the container has one uniform data model to post-process and instantiate from, regardless of source. This enables BeanFactoryPostProcessors, placeholder resolution, and consistent lifecycle handling.

saying these in an interview costs you the question

  • Saying a BeanDefinition IS the bean object (it is only metadata).
  • Claiming beans are instantiated the moment their definition is registered (instantiation happens later during refresh, and lazily for lazy-init).
  • Thinking annotations bypass BeanDefinitions — @Component/@Bean are also turned into BeanDefinitions.

context

open as a page

What is the difference between BeanFactory and ApplicationContext in Spring?

level: juniorimportance: must knowfreq 85%

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.

open as a page

What is an ApplicationContext, and what are the main concrete implementations you would instantiate?

level: juniorimportance: must knowfreq 70%

basics

~10 s

ApplicationContext is Spring's IoC container that creates, wires, and manages beans. Common implementations: AnnotationConfigApplicationContext (Java/annotation config), ClassPathXmlApplicationContext (XML config), and GenericApplicationContext (flexible, programmatic registration).

open as a page

What is a Spring FactoryBean and how does it differ from an ordinary bean?

level: juniorimportance: must knowfreq 55%

basics

~20 s

A FactoryBean is a bean whose job is to build another object. When you look it up or inject it by name, Spring hands you what its getObject() method returns, not the FactoryBean instance itself.

open as a page

What is a parent-child (hierarchical) ApplicationContext in Spring, and which direction does bean visibility flow between the two levels?

level: juniorimportance: must knowfreq 55%

basics

~20 s

A child ApplicationContext can be linked to a parent. Beans defined in the parent are visible to the child, but beans defined in the child are NOT visible to the parent. Visibility flows one way: parent-to-child.

open as a page

Explain eager singleton pre-instantiation in ApplicationContext versus lazy lookup in BeanFactory. Why does it matter?

level: middleimportance: must knowfreq 70%

basics

~20 s

A plain BeanFactory creates a bean only when you first ask for it (lazy). An ApplicationContext creates all non-lazy singleton beans up front at startup (eager), so configuration mistakes fail immediately instead of later at runtime.

open as a page

Explain the three FactoryBean methods: getObject(), getObjectType(), and isSingleton().

level: middleimportance: must knowfreq 45%

basics

~20 s

getObject() returns the product bean. getObjectType() returns that product's class (or null if unknown) so Spring can autowire by type. isSingleton() tells Spring whether to build the product once and cache it (true) or call getObject() each time (false).

open as a page

How does bean resolution delegate from a child context to its parent, and what happens when the child defines a bean with the same name as one in the parent?

level: middleimportance: must knowfreq 48%

basics

~20 s

When the child can't find a bean locally, it asks its parent (delegation upward). If the child defines a bean with the same name as the parent, the child's bean 'hides' the parent's for lookups made from the child — both instances can still exist independently.

open as a page

Explain the key BeanDefinition flags — scope, lazy-init, primary, and autowire-mode — and their exact semantics and edge cases.

level: seniorimportance: must knowfreq 50%

basics

~10 s

Scope controls instance lifecycle (singleton vs prototype/web). Lazy-init delays singleton creation until first use. Primary marks the preferred autowire candidate among several. Autowire-mode is the legacy XML setting (byName/byType/constructor) for automatic dependency resolution.

open as a page

Walk through what happens when refresh() is called on an ApplicationContext.

level: seniorimportance: must knowfreq 60%

basics

~10 s

refresh() is the startup routine: it prepares and loads the bean factory, applies configuration post-processors, registers post-processors, sets up the message source, event multicaster, and listeners, eagerly creates all non-lazy singletons, then publishes ContextRefreshedEvent.

open as a page

In classic Spring MVC, explain the split between the root WebApplicationContext and each DispatcherServlet's context. What goes where, and why?

level: seniorimportance: must knowfreq 45%

basics

~20 s

The root context (loaded by ContextLoaderListener) holds shared beans: services, repositories, datasource. Each DispatcherServlet creates a child context for web beans: controllers, handler mappings, view resolvers. Controllers can inject root services; root beans can't see web beans.

open as a page

What are the main BeanDefinition implementations (RootBeanDefinition, GenericBeanDefinition, ChildBeanDefinition, AnnotatedBeanDefinition) and when is each used?

level: middleimportance: should knowfreq 45%

basics

~10 s

GenericBeanDefinition is the general-purpose, modern definition you create. RootBeanDefinition is the fully-resolved internal one the container uses at runtime. ChildBeanDefinition inherits from a parent (legacy). AnnotatedBeanDefinition adds annotation metadata for scanned/@Bean components.

open as a page

What is BeanDefinitionRegistry and how do you build/register a definition with BeanDefinitionBuilder?

level: middleimportance: should knowfreq 40%

basics

~20 s

BeanDefinitionRegistry is the container's registry of BeanDefinitions keyed by bean name — it lets you register, remove, and look up definitions. BeanDefinitionBuilder is a fluent helper to construct a BeanDefinition, then you call registry.registerBeanDefinition(name, def).

open as a page

Walk through the getBean overloads on BeanFactory and when you'd use each.

level: middleimportance: should knowfreq 45%

basics

~20 s

getBean can look a bean up by name (getBean("id")), by type (getBean(MyType.class)), by name and type together, or by type plus constructor arguments (getBean(MyType.class, args...)) for prototype beans. Name lookup returns Object; type lookup is type-safe.

open as a page

What is an ApplicationContextInitializer and when does it run?

level: middleimportance: should knowfreq 30%

basics

~10 s

ApplicationContextInitializer is a callback you implement to configure the ConfigurableApplicationContext before refresh() is called. It's commonly used in Spring Boot to add property sources, activate profiles, or register beans very early in startup.

open as a page

What does the '&' prefix do when looking up a bean, and when do you need it?

level: middleimportance: should knowfreq 40%

basics

~10 s

Prefixing a bean name with '&' tells the container to return the FactoryBean itself instead of the object it produces. So getBean("foo") gives the product, and getBean("&foo") gives the factory.

open as a page

What are merged bean definitions, and why does Spring compute a RootBeanDefinition per bean at runtime?

level: seniorimportance: should knowfreq 30%

basics

~20 s

A merged bean definition flattens a child definition together with its parent(s) into one complete RootBeanDefinition. Spring instantiates beans from this merged, fully-resolved copy so parent-inherited settings and defaults are all applied in one place.

open as a page

Why do @Autowired, @PostConstruct, and AOP proxies work in an ApplicationContext but not in a bare BeanFactory? Explain the BeanPostProcessor role.

level: seniorimportance: should knowfreq 40%

basics

~20 s

Those features are implemented by BeanPostProcessors. ApplicationContext automatically detects and registers BeanPostProcessor beans during startup; a raw BeanFactory does not, so annotation injection, lifecycle callbacks, and proxying silently don't happen unless you register the processors yourself.

open as a page

How do you register beans programmatically with GenericApplicationContext and registerBean, and when would you do that?

level: seniorimportance: should knowfreq 35%

basics

~10 s

Create a GenericApplicationContext, call registerBean(...) passing a class (and optionally a supplier/lambda and customizers) for each bean, then call refresh() once. This is the functional bean-registration style — useful for lightweight, reflection-free wiring.

open as a page

How does the container treat a FactoryBean's product regarding caching and bean lifecycle (post-processing, DI)?

level: seniorimportance: should knowfreq 28%

basics

~20 s

For a singleton FactoryBean the container calls getObject() once and caches the product. The product is NOT a fully lifecycle-managed bean: it skips @Autowired injection and init callbacks, though BeanPostProcessors' after-initialization phase is applied to it.

open as a page

What are the practical pitfalls of context hierarchies, and when would you deliberately choose a hierarchy over a single flat context?

level: seniorimportance: should knowfreq 22%

basics

~20 s

Pitfalls: duplicate singletons from overlapping scans, accidental name-shadowing, getBeansOfType not seeing ancestors, and AOP/transactions breaking on the wrong copy. Use a hierarchy only to share one root layer across several isolated children (e.g., multiple DispatcherServlets); otherwise prefer a single flat context.

open as a page

How can you inspect or mutate BeanDefinitions before beans are instantiated, and what are the ordering/safety rules?

level: principalimportance: should knowfreq 25%

basics

~20 s

Use a BeanFactoryPostProcessor (or BeanDefinitionRegistryPostProcessor) which Spring invokes after all definitions are loaded but before any bean is created. Through the registry/factory you read and edit definitions — change scope, property values, lazy flag, etc. — and the container instantiates from your changes.

open as a page

At the API level, how do you wire a parent context, and how does the bean factory implement hierarchical lookup? Cover ConfigurableApplicationContext.setParent and HierarchicalBeanFactory.getParentBeanFactory.

level: principalimportance: should knowfreq 25%

basics

~10 s

Call ConfigurableApplicationContext.setParent(parent) before refresh(). Internally the child's BeanFactory records the parent via setParentBeanFactory, and HierarchicalBeanFactory.getParentBeanFactory() exposes it. Lookups check locally, then delegate to the parent factory.

open as a page

Is there ever a legitimate reason to use a raw BeanFactory / DefaultListableBeanFactory instead of an ApplicationContext? What trade-offs are you making?

level: principalimportance: nice to knowfreq 20%

basics

~20 s

Almost never in application code. A raw DefaultListableBeanFactory makes sense only for low-level tooling, dynamic programmatic bean registration, or extreme resource constraints — accepting that you lose auto post-processing, events, i18n, resource patterns, and eager fail-fast startup.

open as a page

Which contexts can be refreshed more than once, and what are the close()/shutdown semantics?

level: principalimportance: nice to knowfreq 18%

basics

~10 s

AbstractRefreshableApplicationContext subclasses (like ClassPathXmlApplicationContext) can call refresh() repeatedly to reload definitions; GenericApplicationContext (and AnnotationConfigApplicationContext) can only refresh once. close() stops lifecycle beans and runs destroy callbacks; registerShutdownHook ties that to JVM exit.

open as a page

What does SmartFactoryBean add over FactoryBean, and when would you choose a FactoryBean over a plain @Bean factory method?

level: principalimportance: nice to knowfreq 18%

basics

~20 s

SmartFactoryBean extends FactoryBean with isEagerInit() (create the singleton product eagerly at startup instead of lazily) and isPrototype() (mark the product as a prototype). Choose a FactoryBean over @Bean only for reusable, framework-level construction needing type introspection.

open as a page