What is a JDK dynamic proxy, and what does Spring require of a bean before it can create one for it?
answer
- java.lang.reflect.Proxy at runtime
- must implement an interface
- all calls -> InvocationHandler.invoke
- interface-based, not subclass
- no interface -> CGLIB fallback
basics
~20 sA JDK dynamic proxy is a class the JVM builds at runtime that implements the same interface(s) as your bean and forwards calls to it. Spring can only create one if the target implements an interface.
solid answer
~40 sA JDK dynamic proxy is a proxy object generated at runtime by java.lang.reflect.Proxy. It implements one or more interfaces you specify and routes every method call through an InvocationHandler, which can run extra logic (like an aspect) before or after delegating to the real target. Spring AOP uses JDK dynamic proxies by default when the target bean implements at least one interface — the proxy implements those same interfaces so callers depending on the interface get the proxy transparently. The key requirement is exactly that: the target must implement an interface, because the generated proxy is interface-based. If the bean implements no interface, Spring falls back to CGLIB (subclass-based) proxying instead. This is why the classic advice 'program to interfaces' matters in Spring AOP contexts.
code
java · 20 linespublic interface GreetingService {
String greet(String name);
}
@Service
public class GreetingServiceImpl implements GreetingService {
@Override
public String greet(String name) {
return "Hello, " + name;
}
}
// Because GreetingServiceImpl implements an interface,
// Spring AOP wraps it in a JDK dynamic proxy that implements
// GreetingService. Inject by the INTERFACE:
@Component
class Caller {
private final GreetingService service; // <-- interface type
Caller(GreetingService service) { this.service = service; }
}go deeper
Know the one-line definition and the interface requirement.
Explain the InvocationHandler routing and the JDK-vs-CGLIB default choice.
Connect it to Spring AOP wrapping, program-to-interfaces, and proxyTargetClass.
Frame design trade-offs: interface discipline, which methods get advised, and when to force CGLIB.
## What it is A **JDK dynamic proxy** is an object created at *runtime* by the standard library class `java.lang.reflect.Proxy`. Given a set of Java **interfaces**, the JVM synthesizes a brand-new class that `implements` all of those interfaces, then hands you an instance of it. You never write this class — it exists only in memory. Every method call on the proxy is funneled into a single method: `InvocationHandler.invoke(Object proxy, Method method, Object[] args)`. Your handler decides what to do — typically run some cross-cutting logic (logging, a transaction, a security check) and then call `method.invoke(target, args)` to delegate to the **real object** (the *target*). ## Why Spring uses it **Spring AOP** implements aspects (things declared with `@Transactional`, `@Async`, `@Cacheable`, or custom `@Aspect` advice) by wrapping your bean in a proxy. When a caller invokes a business method, the call hits the proxy first; the proxy runs the advice, then forwards to your actual bean. Spring picks the proxy strategy automatically: - If the target bean **implements at least one interface**, Spring uses a **JDK dynamic proxy** by default. The proxy implements those same interfaces. - If the target implements **no interface**, Spring falls back to **CGLIB**, which creates a runtime *subclass* of the concrete class. ## The hard requirement A JDK dynamic proxy is **interface-based**. `Proxy.newProxyInstance(classLoader, interfaces, handler)` takes an array of *interfaces* — there is no way to make it implement or extend a concrete class. So the target **must implement an interface** for JDK proxying to be possible. ## Consequence: the proxy is NOT the concrete type Because the generated proxy `implements MyService` (the interface) but does **not** extend `MyServiceImpl` (the class), the proxy is assignable to the interface but **not** to the concrete class. Injecting or casting by concrete type fails. ## When to use / when it matters - Prefer depending on **interfaces** in Spring beans so JDK proxying works cleanly. - Only methods **declared on the proxied interface** get advised; a public method that exists on the class but not the interface is invisible to the proxy. - To force subclass-based (CGLIB) proxying instead, set `@EnableAspectJAutoProxy(proxyTargetClass = true)` (or `spring.aop.proxy-target-class=true`). ## Key terms - **Target / target object**: your real bean the proxy wraps. - **InvocationHandler**: the single interception point for all proxied calls. - **Proxy class**: the runtime-generated class that also extends `java.lang.reflect.Proxy`.
- What happens if the target bean implements no interface at all?Spring can't build a JDK dynamic proxy (it needs an interface), so it falls back to CGLIB, generating a runtime subclass of the concrete class instead.
- Which method receives every call made on a JDK proxy?InvocationHandler.invoke(Object proxy, Method method, Object[] args) — it runs your logic and typically delegates via method.invoke(target, args).
saying these in an interview costs you the question
- Saying a JDK dynamic proxy subclasses the concrete class (that's CGLIB).
- Claiming JDK proxies work on any class regardless of interfaces.
- Thinking the proxy is written/generated at compile time.