Contrast XML <lookup-method> and <replaced-method>. What is the MethodReplacer interface and how do they relate to CGLIB?
answer
- <lookup-method> = XML @Lookup, returns named bean each call
- <replaced-method> = swap whole body via MethodReplacer
- reimplement(obj, method, args)
- <arg-type> disambiguates overloads
- both = CGLIB subclass, non-final required
basics
~10 s<lookup-method> makes Spring override a method to return a named bean each call — the XML form of @Lookup. <replaced-method> swaps a method's whole implementation with a MethodReplacer bean. Both use CGLIB subclassing.
solid answer
~40 sBoth are XML method-injection features implemented by generating a **CGLIB subclass** of the target bean. `<lookup-method name="createX" bean="xPrototype"/>` overrides `createX()` so each call returns a fresh lookup of bean `xPrototype` — it is exactly the XML equivalent of `@Lookup`, aimed at pulling prototypes into singletons. `<replaced-method name="m" replacer="myReplacer"/>` is more general: it replaces the **entire body** of any method `m` with the logic of a Spring bean implementing `org.springframework.beans.factory.support.MethodReplacer`, whose single method `Object reimplement(Object obj, Method method, Object[] args)` runs instead of the original. It isn't limited to returning beans — you can rewrite arbitrary behavior. Overloaded methods are disambiguated with nested `<arg-type>` elements. Both require the class and method to be non-final so CGLIB can override them. `<replaced-method>` is rarely used today; `<lookup-method>`/`@Lookup` cover the common prototype-injection case.
go deeper
Aware <lookup-method> exists as the XML form of @Lookup.
Can explain <lookup-method> returns a fresh named bean per call via CGLIB.
Must distinguish <replaced-method> + MethodReplacer.reimplement and <arg-type> overload handling, and the shared CGLIB/non-final constraints.
Should position both below AOP and advise modern alternatives (ObjectProvider, strategy beans, aspects).
## Two XML method-injection tools Spring's XML configuration offers two ways to have the container override a bean method at runtime. Both are implemented the same way — Spring uses **CGLIB** to create a dynamic **subclass** of your bean and overrides the target method. ### 1. `<lookup-method>` — the XML twin of @Lookup ```xml <bean id="reportService" class="com.acme.ReportService"> <lookup-method name="newBuilder" bean="reportBuilder"/> </bean> <bean id="reportBuilder" class="com.acme.ReportBuilder" scope="prototype"/> ``` - `name` = the method to override (typically abstract or a no-arg concrete method). - `bean` = the bean id to return on each invocation. Spring overrides `newBuilder()` to do `getBean("reportBuilder")`, so a **fresh prototype** is returned every call. This is the classic 'prototype into singleton' fix — identical in effect to `@Lookup`, just expressed in XML. ### 2. `<replaced-method>` — arbitrary method replacement ```xml <bean id="myBean" class="com.acme.MyBean"> <replaced-method name="compute" replacer="computeReplacer"> <arg-type>java.lang.String</arg-type> </replaced-method> </bean> <bean id="computeReplacer" class="com.acme.ComputeReplacer"/> ``` ```java public class ComputeReplacer implements MethodReplacer { @Override public Object reimplement(Object obj, Method method, Object[] args) { // runs INSTEAD of MyBean.compute(...) return "replaced:" + args[0]; } } ``` - `replacer` = a bean implementing **`org.springframework.beans.factory.support.MethodReplacer`**. - `MethodReplacer` has one method: `Object reimplement(Object obj, Method method, Object[] args)`, receiving the target instance, the reflected `Method`, and the call arguments; whatever it returns becomes the method's result. - `<arg-type>` disambiguates **overloaded** methods (you can list one or more argument type fragments; substring matching is allowed). Unlike `<lookup-method>`, `<replaced-method>` is **not** about returning a bean — it lets you substitute *any* logic for a method. It is effectively a lightweight, container-native form of method interception without full AOP. ## How they compare | Aspect | `<lookup-method>` / `@Lookup` | `<replaced-method>` | |---|---|---| | Purpose | Return a fresh (usually prototype) bean per call | Replace a method's entire implementation | | Body source | Container `getBean` | Your `MethodReplacer` bean | | Return value | The looked-up bean | Whatever `reimplement` returns | | Overload handling | n/a (usually no-arg) | `<arg-type>` elements | | Annotation form | `@Lookup` | none (XML only) | | Typical use today | Common | Rare | ## Shared mechanics and constraints - Both generate a **CGLIB subclass**, so the class and the overridden method must be **non-final** (and not `private`/`static`), and the class must be instantiable. - Because a subclass is created, the bean instance you receive is a CGLIB-enhanced subtype. - These sit below full Spring AOP: they're bean-definition-level overrides, not aspect weaving. ## When to reach for each - Need a prototype inside a singleton, XML config → `<lookup-method>` (or `@Lookup` in annotations). - Need to swap a method's behavior without editing the class or writing an aspect (legacy XML apps) → `<replaced-method>`. In modern code this is almost always better handled by AOP, a strategy bean, or plain composition.
- Why would you need <arg-type> in a <replaced-method> declaration?To disambiguate overloaded methods that share a name but differ in parameter types. <arg-type> pins the replacement to the specific overload by naming its argument type(s).
- Is <replaced-method> the same as Spring AOP method interception?No. It's a bean-definition-level CGLIB override that replaces the whole method body with a MethodReplacer. AOP weaves advice around a join point and supports pointcuts, ordering, and proceed(); <replaced-method> is a simpler, coarser total replacement.
saying these in an interview costs you the question
- Confusing <replaced-method> with AOP around advice
- Thinking <replaced-method> can only return beans (it can return anything)
- Not knowing MethodReplacer.reimplement's signature
- Claiming these use JDK dynamic proxies instead of CGLIB