Backend Development 11 min read

Understanding JDK and CGLIB Dynamic Proxies in Java

This article explains the principles, advantages, and implementation details of Java's JDK dynamic proxy and CGLIB proxy mechanisms, providing step‑by‑step code examples that demonstrate how to enhance method calls such as user registration with validation logic.

Top Architect
Top Architect
Top Architect
Understanding JDK and CGLIB Dynamic Proxies in Java

Dynamic proxies are widely used in frameworks like Spring AOP and MyBatis to add behavior to existing classes without modifying their source code; they rely on reflection and bytecode generation to create subclasses or interface implementations at runtime.

JDK Dynamic Proxy

The JDK implementation consists of two core components: Proxy and InvocationHandler . Proxy creates a proxy class that implements the target interface, while InvocationHandler intercepts method calls and forwards them to the real object after optional enhancement.

Example code:

package com.taolong;

public class User {
    private String name;
    private Integer age;
    private String password;
    // getters and setters omitted for brevity
    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + ", password=" + password + "]";
    }
}
package com.taolong.jdk;

public interface UserService {
    void addUser(User user);
}
package com.taolong.jdk;

public class UserServiceImpl implements UserService {
    @Override
    public void addUser(User user) {
        System.out.println("jdk...正在注册用户,用户信息为:" + user);
    }
}
package com.taolong.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class UserServiceInterceptor implements InvocationHandler {
    private Object realObj;
    public UserServiceInterceptor(Object realObject) { this.realObj = realObject; }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (args != null && args.length > 0 && args[0] instanceof User) {
            User user = (User) args[0];
            if (user.getName().length() <= 1) {
                throw new RuntimeException("用户名长度必须大于1");
            }
            if (user.getPassword().length() <= 6) {
                throw new RuntimeException("密码长度必须大于6");
            }
        }
        Object result = method.invoke(realObj, args);
        System.out.println("用户注册成功...");
        return result;
    }
}
package com.taolong.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class ClientTest {
    public static void main(String[] args) {
        User user = new User();
        user.setName("hongtaolong");
        user.setPassword("hong"); // password length < 6 triggers validation
        user.setAge(23);
        UserService delegate = new UserServiceImpl();
        InvocationHandler handler = new UserServiceInterceptor(delegate);
        UserService proxy = (UserService) Proxy.newProxyInstance(
                delegate.getClass().getClassLoader(),
                delegate.getClass().getInterfaces(),
                handler);
        System.out.println("动态代理类:" + proxy.getClass());
        proxy.addUser(user);
    }
}

CGLIB Dynamic Proxy

CGLIB (Code Generation Library) uses ASM to generate bytecode at runtime. It creates a subclass of the target class, so it can proxy classes that do not implement interfaces, but it cannot intercept final methods.

Key components are Enhancer (specifies the superclass and callback) and MethodInterceptor (receives method calls via intercept ).

package com.taolong.cglib;

import net.sf.cglib.proxy.MethodInterceptor;
import java.lang.reflect.Method;

public class UserServiceCglibInterceptor implements MethodInterceptor {
    private Object realObject;
    public UserServiceCglibInterceptor(Object realObject) { this.realObject = realObject; }
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        if (args != null && args.length > 0 && args[0] instanceof User) {
            User user = (User) args[0];
            if (user.getName().length() <= 1) {
                throw new RuntimeException("用户名长度必须大于1");
            }
            if (user.getPassword().length() <= 6) {
                throw new RuntimeException("密码长度必须大于6");
            }
        }
        Object result = method.invoke(realObject, args);
        System.out.println("用户注册成功...");
        return result;
    }
}
package com.taolong.cglib;

public class UserServiceImplCglib {
    public final void addUser(User user) {
        System.out.println("cglib...正在注册用户,用户信息为:" + user);
    }
}
package com.taolong.cglib;

import net.sf.cglib.proxy.Enhancer;

public class ClientTest {
    public static void main(String[] args) {
        User user = new User();
        user.setName("hongtaolong");
        user.setPassword("hong");
        user.setAge(23);
        UserServiceImplCglib delegate = new UserServiceImplCglib();
        UserServiceCglibInterceptor interceptor = new UserServiceCglibInterceptor(delegate);
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(delegate.getClass());
        enhancer.setCallback(interceptor);
        UserServiceImplCglib cglibProxy = (UserServiceImplCglib) enhancer.create();
        System.out.println("动态代理类父类:" + cglibProxy.getClass().getSuperclass());
        cglibProxy.addUser(user);
    }
}

Running the examples shows that the JDK proxy works only with interfaces, while CGLIB can proxy concrete classes but cannot enhance final methods, as demonstrated by the final void addUser method.

Conclusion

JDK dynamic proxy is built‑in, requires no external libraries, and can proxy only interfaces.

CGLIB creates subclasses to proxy any class, but it cannot intercept final methods.

Both mechanisms rely on reflection and bytecode manipulation to add cross‑cutting concerns such as validation.

JavaAOPbackend developmentJDKDynamic ProxyCglib
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

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.