skip to content

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