Fundamentals 15 min read

Understanding Java Dynamic Proxies: JDK and CGLIB Implementations

This article explains the concepts, implementation mechanisms, performance considerations, and practical code examples of Java static and dynamic proxies, covering both JDK's proxy based on interfaces and CGLIB's subclass‑based proxy, and compares their suitable use cases.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Understanding Java Dynamic Proxies: JDK and CGLIB Implementations

Preface

The previous article introduced Java reflection; this piece focuses on the implementation mechanism of dynamic proxies, which include both JDK dynamic proxies and CGLIB dynamic proxies. Although they achieve the same goal, their underlying implementations differ significantly.

We will explore these two kinds of dynamic proxies through code, examining their performance, underlying principles, and application scenarios.

Proxy Pattern

Before diving into dynamic proxies, Java's proxy pattern is introduced, which consists of two types:

Static proxy : the proxy class is written and compiled by the programmer before runtime.

Dynamic proxy : includes JDK dynamic proxy and CGLIB dynamic proxy, created at runtime via reflection.

The proxy pattern provides a proxy object that holds a reference to the real object and can add behavior before or after invoking the real object's methods.

An example class diagram shows a common interface shared by the proxy and the delegate class.

To illustrate the pattern, a car‑buying scenario is used. The following code demonstrates a static proxy:

public interface Person{
    void buyCar();
}
public class Myself implements Person {

    @Override
    public void buyCar() {
        System.out.println("我要买车了");
    }
}
public class CarProxy implements Person{

    private Myself  myself ;

    public CarProxy(final Myself  myself ) {
        this.myself = myself ;
    }

    @Override
    public void buyCar() {
        System.out.println("买车前去找车源");
        myself .buyCar();
        System.out.println("买车后办理手续");
    }
}

The static proxy works but has the drawback of increasing the number of classes, making maintenance harder. This motivates the use of dynamic proxies, which abstract the repetitive proxy logic into a generic handler.

In dynamic proxies, an InvocationHandler is introduced to centralize the method‑invocation logic.

JDK Dynamic Proxy

JDK dynamic proxies generate proxy classes at runtime. The process involves:

Obtaining all interfaces implemented by the delegate class.

Generating a proxy class whose name follows the pattern com.sun.proxy.$ProxyXXX .

Creating bytecode for the proxy class and loading it into the JVM.

Instantiating the proxy class.

Providing an InvocationHandler that overrides invoke to add pre‑ and post‑processing.

Creating the proxy instance and invoking methods.

The following code shows the complete JDK dynamic proxy example:

public interface Person{
    void buyCar();
}
public class Myself implements Person {

    @Override
    public void buyCar() {
        System.out.println("我要买车了");
    }
}
public class InvocationHandlerImpl implements InvocationHandler {
  
    private Person person;
      
    public InvocationHandlerImpl(Person  person){
        this.person=person;
    }
      
    @Override
    public Object invoke(Object proxy, Method method,  Object[] args) throws Throwable {
        System.out.println("买车前开始找车源。。。。");
        method.invoke(person, args);
        System.out.println("买车后办理手续。。。。");
        return null;
    }
}
public class Test {
  
    public static void main(String[] args) {
        Myself myself= new Myself();
        // create proxy: ClassLoader, interfaces, InvocationHandler
        Object o = Proxy.newProxyInstance(myself.getClass().getClassLoader(), myself.getClass().getInterfaces(), new InvocationHandlerImpl(myself));
        Person person= (Person) o;
        person.buyCar();
    }
}

Decompiling the generated proxy class (using jd‑gui ) reveals that it extends java.lang.reflect.Proxy , implements the target interface, and forwards all method calls to the supplied InvocationHandler via the invoke method.

CGLIB Dynamic Proxy

JDK dynamic proxies require an interface; CGLIB can proxy concrete classes by generating a subclass at runtime using bytecode manipulation. The subclass intercepts method calls via a MethodInterceptor .

Key steps performed by CGLIB:

Identify all non‑final public methods of the target class.

Convert these methods into bytecode.

Load the generated bytecode as a Class object.

Use a MethodInterceptor to implement the proxy logic.

Example CGLIB proxy code:

public class Myself {

    @Override
    public void buyCar() {
        System.out.println("I'm going to buy a house");
    }
}
public class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args,  MethodProxy proxy) throws Throwable {
        System.out.println("买车前开始找车源。。。。");
        proxy.invokeSuper(obj, args);
        System.out.println("买车后办理手续。。。。");
        return null;
    }
  
}
public class Test {
    public static void main(String[] args) {
        Myself myself= new Myself();
        MyMethodInterceptor myMethodInterceptor = new MyMethodInterceptor();
        // CGLIB enhancer creates the proxy
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(myself.getClass());
        enhancer.setCallback(myMethodInterceptor);
        Myself proxy =(Myself)enhancer.create();
        proxy.buyCar();
    }
}

CGLIB offers higher runtime performance than JDK proxies but incurs a larger proxy‑creation cost. Therefore, CGLIB is preferable for singleton beans where proxies are created infrequently, while JDK dynamic proxies suit scenarios requiring many short‑lived proxies.

Both proxy mechanisms are foundational to Spring AOP, which relies on JDK proxies for interface‑based advice and CGLIB proxies for class‑based advice.

— End of article —

JavaReflectionJDKDesign PatternDynamic ProxyCGLIB
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.