What problem does method injection (@Lookup / lookup-method) solve when a singleton bean depends on a prototype bean?
answer
- singleton created once -> prototype captured once
- inject a method, not an instance
- @Lookup / <lookup-method>
- CGLIB subclass overrides method -> getBean
- avoids ApplicationContextAware coupling
basics
~10 sA singleton is created once, so a prototype injected normally is captured only once and reused forever. Method injection lets the singleton ask the container for a fresh prototype on every call.
solid answer
~40 sA singleton bean is instantiated a single time, so any dependency injected into it — even a prototype — is resolved exactly once and the same instance is reused for the singleton's whole life. That defeats the point of a prototype, which should give a new object per request. Method injection fixes this: instead of injecting the prototype instance, you declare a lookup method that Spring overrides (via a CGLIB subclass) so each call returns a freshly resolved bean from the container. With @Lookup you annotate a (usually abstract) method; in XML you use <lookup-method>. This keeps the singleton a singleton while still handing it a new prototype every time the method runs, without the singleton needing a direct reference to the ApplicationContext.
go deeper
Must grasp the 'singleton resolves its dependencies once' idea and that method injection gives a fresh instance per call.
Should name @Lookup vs <lookup-method> and the CGLIB-subclass mechanism.
Should compare against ObjectProvider/Provider and explain the ApplicationContextAware coupling being avoided.
Should discuss when method injection is the wrong tool (prefer ObjectProvider) and CGLIB proxying constraints.
## The core problem: scope mismatch Spring beans have scopes. A **singleton** bean is created **once** by the container and cached; every injection point receives that same shared instance. A **prototype** bean is meant to produce a **brand-new instance every time it is requested**. Dependency injection happens **once, at bean-creation time**. So if you inject a prototype into a singleton the normal way (constructor or field), Spring resolves the prototype exactly once — when it builds the singleton — and stores that single instance in the singleton's field forever. Every method call on the singleton then reuses the *same* prototype object. The prototype's 'new instance per request' promise is silently broken. ```java @Component // singleton class Processor { @Autowired Task task; // prototype, but resolved ONCE — always the same object void run() { task.execute(); } // same task every time } ``` ## The fix: method injection Instead of injecting the *instance*, you inject a *method that fetches a fresh instance*. Spring supports this in two forms: - **`@Lookup`** (annotation): annotate a method — typically `abstract` — whose body Spring generates. Each invocation returns a newly resolved bean of the method's return type. - **`<lookup-method>`** (XML): the same mechanism declared in XML on a `<bean>`. Under the hood Spring creates a **CGLIB subclass** of your bean and overrides the lookup method to call `getBean(...)` on the container, so each call yields a fresh prototype. ```java @Component abstract class Processor { void run() { createTask().execute(); } // fresh Task each call @Lookup protected abstract Task createTask(); // Spring implements this } ``` ## Why not just inject ApplicationContext and call getBean? You can (`context.getBean(Task.class)`), and it works, but it couples your business class to the Spring container API — an anti-pattern that hurts testability and clarity. Method injection is the container-native way to express 'give me a fresh one each time' without that coupling. ## When to use it - A **long-lived (singleton) bean** needs a **shorter-lived (prototype) collaborator** on demand. - You want to avoid `ApplicationContextAware` / manual `getBean`. In modern code, injecting `ObjectProvider<Task>` / `Provider<Task>` and calling `getObject()` / `get()` is usually preferred (no CGLIB, no abstract methods) — but `@Lookup` remains the classic container-overridden approach and still appears widely.
- If a singleton needs a fresh prototype each call, name two alternatives to @Lookup.Inject ObjectProvider<T> (or JSR-330 Provider<T>) and call getObject()/get() per request; or inject ApplicationContext/BeanFactory and call getBean() (works but couples code to the container). ObjectProvider is the modern preferred option.
- Does method injection change the scope of the singleton?No. The outer bean stays a singleton — created once and cached. Only the lookup method returns a new instance per call; the singleton itself is not recreated.
saying these in an interview costs you the question
- Claiming a prototype injected normally into a singleton gives a new instance each call
- Saying @Lookup makes the enclosing bean a prototype
- Believing you must inject ApplicationContext to get fresh prototypes