What is a CGLIB proxy in Spring, and how does it differ from a JDK dynamic proxy?
answer
- runtime subclass overrides methods
- no interface needed
- org.springframework.cglib repackaged
- JDK proxy = interfaces, CGLIB = subclass
- Boot default proxyTargetClass=true
basics
~10 sA CGLIB proxy is a runtime-generated subclass of your target class that overrides its methods to add behavior like transactions. Unlike a JDK dynamic proxy, it doesn't need the class to implement an interface.
solid answer
~40 sSpring creates proxies to wrap beans with cross-cutting behavior (AOP advice, @Transactional, @Async, @Cacheable). There are two mechanisms. A JDK dynamic proxy implements the target's interfaces and requires at least one interface. A CGLIB proxy generates a runtime subclass of the concrete target class, overriding each non-final method to route calls through the interceptor chain. Because CGLIB subclasses, it works on classes with no interfaces. Spring ships a repackaged copy of the library under org.springframework.cglib so there's no external dependency. Spring Boot defaults to CGLIB (proxyTargetClass=true) even when interfaces exist, for consistency. The key limitation: since it subclasses, final classes can't be proxied and final, private, or static methods can't be overridden, so advice on those is silently skipped.
code
java · 12 lines// No interface — Spring must use a CGLIB subclass proxy to advise @Transactional
@Service
public class PaymentService {
@Transactional
public void charge(long accountId, Money amount) {
// proxy opens a tx before this body runs, commits/rolls back after
}
}
// The bean Spring injects is actually a runtime-generated subclass:
// class PaymentService$$SpringCGLIB$$0 extends PaymentService { ... }go deeper
Know CGLIB = runtime subclass, works without interfaces, adds behavior like @Transactional.
Contrast JDK proxy (interface) vs CGLIB (subclass) and know Boot defaults to CGLIB.
Explain the interceptor override mechanism and repackaged org.springframework.cglib.
Discuss proxy-strategy tradeoffs, uniform CGLIB default rationale, and design implications for API surfaces.
**What a proxy is.** A proxy is a stand-in object that looks like your bean but wraps each method call with extra behavior (an "interceptor chain"). Spring uses proxies to implement AOP aspects and annotations such as `@Transactional`, `@Async`, `@Cacheable`, and `@Retryable`. When you call a method on the injected bean, you're actually calling the proxy, which runs the advice (e.g. open a transaction) and then delegates to your real code. **Two proxy strategies in Spring.** 1. **JDK dynamic proxy** — built into the JDK via `java.lang.reflect.Proxy`. It creates an object that *implements the same interfaces* as the target. It requires the bean to implement at least one interface, and only methods declared on those interfaces can be advised. The proxy holds a reference to the target and is a *separate* object from it. 2. **CGLIB proxy** — CGLIB (Code Generation Library) generates a brand-new class at runtime that *extends* (subclasses) your concrete target class. Spring bundles a repackaged copy of CGLIB under `org.springframework.cglib.*` (relocated from the original `net.sf.cglib`), so you don't add a dependency yourself. The generated subclass overrides every non-final, non-private method and inserts a `MethodInterceptor` call, which runs the advice chain and then invokes the original method body via the superclass. **Why CGLIB exists.** Not every bean implements an interface. Plenty of `@Service` / `@Component` classes are plain concrete classes. JDK proxies can't wrap those, so CGLIB subclassing fills the gap. **How Spring chooses.** Historically Spring used JDK proxies when the target implemented interfaces and CGLIB otherwise. You can force CGLIB with `proxyTargetClass = true` (on `@EnableAspectJAutoProxy`, `@EnableTransactionManagement`, etc.). **Spring Boot sets `proxyTargetClass = true` by default**, so Boot apps use CGLIB even for interface-bearing beans — this avoids surprises where injecting the concrete type fails. **Core limitations (because it subclasses):** - A `final` class cannot be subclassed → cannot be proxied by CGLIB. - `final` methods cannot be overridden → advice on them is silently skipped. - `private` methods aren't inherited/overridable → not advised. - `static` methods belong to the class, not instances → not proxied. **Gotcha — self-invocation.** Advice only fires when a call goes *through the proxy*. If a method calls another advised method on `this`, the call bypasses the proxy (it's a plain `super`-level call within the same object), so the second method's advice does not run. This is true for both proxy types. **When to use.** Prefer JDK proxies when you code to interfaces (cleaner, no subclassing constraints); use CGLIB when there's no interface, or use Boot's CGLIB default for uniform behavior. Avoid `final` on classes/methods you intend to advise.
- If a class implements an interface, which proxy does Spring use?By default plain Spring uses a JDK dynamic proxy; but Spring Boot sets proxyTargetClass=true, so Boot uses CGLIB even then. You can also force CGLIB explicitly via proxyTargetClass.
- Where does the CGLIB code come from — do you add a dependency?No. Spring repackages CGLIB inside spring-core under org.springframework.cglib, so it's always available without a separate artifact.
saying these in an interview costs you the question
- Saying CGLIB requires the class to implement an interface (that's JDK proxies)
- Claiming CGLIB modifies/rewrites the original class bytecode (it generates a new subclass)
- Thinking you must add a cglib Maven dependency manually