skip to content

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

level: middleimportance: should knowfreq 45%

answer

  1. by-name (Object), name+type, by-type
  2. args overloads = prototype only
  3. getBean(Class) → NoUnique/NoSuchBean
  4. Prefer ObjectProvider / injection
  5. @Primary resolves ambiguity

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.

solid answer

~40 s

BeanFactory defines several `getBean` overloads. `getBean(String name)` returns `Object` (needs casting). `getBean(String name, Class<T> requiredType)` looks up by name and asserts the type. `getBean(Class<T> requiredType)` resolves by type — throwing `NoUniqueBeanDefinitionException` if multiple candidates exist (unless one is `@Primary`) and `NoSuchBeanDefinitionException` if none. `getBean(String name, Object... args)` and `getBean(Class<T> requiredType, Object... args)` supply explicit constructor/factory arguments — only meaningful for **prototype**-scoped beans, since a singleton is created once and reusing the same singleton with different args throws. For optional or deferred access prefer `ObjectProvider<T>` (`getBeanProvider`) over direct getBean, and remember that pulling beans via getBean is a form of service-locator lookup you should avoid in favor of injection.

code

java · 12 lines
java
// by name (untyped)
Object a = ctx.getBean("orderService");
// by name + type (typed, checked)
OrderService b = ctx.getBean("orderService", OrderService.class);
// by type (throws if 0 or >1 candidates without @Primary)
OrderService c = ctx.getBean(OrderService.class);
// prototype with explicit constructor args
@Scope("prototype") // on the bean definition
Connection conn = ctx.getBean(Connection.class, "jdbc:...", "user");
// preferred for optional/plural: ObjectProvider
ObjectProvider<OrderService> p = ctx.getBeanProvider(OrderService.class);
OrderService d = p.getIfAvailable();

go deeper

for a junior

List by-name and by-type lookups and note by-type is type-safe.

for a middle

Cover all overloads, the ambiguity/absence exceptions, and that args overloads are prototype-only.

for a senior

Contrast with ObjectProvider/getBeanProvider, discuss the service-locator anti-pattern, and @Primary/qualifier resolution.

for a principal

Frame getBean usage as a design decision (framework glue vs app code), discuss dynamic bean creation patterns and ObjectProvider streaming/ordering for plugin architectures.

## The getBean family `getBean` is the container's programmatic lookup API. Injection (`@Autowired`, constructor params) is usually preferred, but `getBean` matters for dynamic/factory scenarios and for understanding the container. ### The overloads (from BeanFactory) 1. **`Object getBean(String name)`** — classic lookup by bean id/name. Returns `Object`; you cast. Throws `NoSuchBeanDefinitionException` if the name is unknown. 2. **`<T> T getBean(String name, Class<T> requiredType)`** — by name, but the container checks the instance is assignable to `requiredType` and returns it typed. Throws `BeanNotOfRequiredTypeException` on mismatch. 3. **`<T> T getBean(Class<T> requiredType)`** — by type. The most common typed form. Resolution rules: - Exactly one candidate → returned. - Multiple candidates → `NoUniqueBeanDefinitionException`, unless exactly one is `@Primary`, or qualifier resolution applies. - Zero candidates → `NoSuchBeanDefinitionException`. 4. **`Object getBean(String name, Object... args)`** — supply explicit arguments to the bean's constructor or factory method. 5. **`<T> T getBean(Class<T> requiredType, Object... args)`** — type-based version of the above. ### The args overloads and scope The `args` variants let you pass runtime constructor/factory-method arguments. This is **only sensible for prototype-scoped beans**: each `getBean` call creates a fresh instance, so passing different args each time is valid. If you call an args overload on a **singleton** that has already been created, Spring throws `BeanDefinitionStoreException` ("Can only specify arguments for the getBean method when referring to a prototype bean definition"). Use it to create parameterized prototypes without wiring a factory yourself. ### Related, better alternatives - **`ObjectProvider<T> getBeanProvider(Class<T>)`** — returns a provider supporting `getIfAvailable()`, `getIfUnique()`, `orderedStream()`, and lazy access. Preferable when a dependency may be absent or multiple. - **`Map<String, T> getBeansOfType(Class<T>)`** and **`String[] getBeanNamesForType(...)`** (on `ListableBeanFactory`) — enumerate all beans of a type. - **`getBeansWithAnnotation(...)`** — find beans by annotation. ### Gotchas - Overuse of `getBean` in application code is a **service-locator anti-pattern**; prefer constructor injection. Reserve `getBean` for frameworks, plugins, or genuinely dynamic lookups. - `getBean(Class)` failing with `NoUniqueBeanDefinitionException` is a very common interview trap — the fix is `@Primary` or a qualifier. - The args overloads silently doing nothing useful for singletons is a classic bug. - `getBean` on a `@Lazy` bean triggers its creation at that moment. ### When to use Use typed `getBean(Class)` in small tools/tests. Use the args overloads to spin up configured prototypes. In real app code, inject instead — or inject `ObjectProvider`/`ObjectFactory` for on-demand, optional, or plural resolution.

  • What happens if you call getBean(MyType.class) and there are two beans of that type?
    NoUniqueBeanDefinitionException — unless one is marked @Primary (or you disambiguate by name/qualifier), in which case that one is returned.
  • Why do the getBean(..., Object... args) overloads only make sense for prototypes?
    Singletons are instantiated once and cached; supplying args to fetch an already-created singleton throws. Prototypes create a fresh instance per call, so per-call constructor/factory args are meaningful.

saying these in an interview costs you the question

  • Thinking getBean(Class, args) reconfigures an existing singleton.
  • Claiming getBean(Class) with multiple candidates silently returns the first one (it throws NoUniqueBeanDefinitionException).
  • Recommending getBean everywhere instead of dependency injection.

context