Proxy Pattern in Java: Static, Dynamic, and Cglib Implementations
This article explains the Proxy design pattern in Java, covering static proxy, dynamic JDK proxy, and Cglib subclass proxy with detailed code examples and discussion of their advantages, limitations, and typical usage in AOP frameworks.
The Proxy pattern provides an alternative way to access a target object through a proxy, allowing additional functionality to be added without modifying the original code.
Static Proxy requires the proxy and the target to implement the same interface. The article defines an IUserDao interface, a UserDao target class, and a UserDaoProxy that adds transaction messages before and after delegating to the target. A test class App demonstrates creating the proxy and invoking save() .
/**
* Interface
*/
public interface IUserDao {
void save();
} /**
* Target object implementation
*/
public class UserDao implements IUserDao {
public void save() {
System.out.println("----已经保存数据!----");
}
} /**
* Static proxy class
*/
public class UserDaoProxy implements IUserDao {
private IUserDao target;
public UserDaoProxy(IUserDao target) { this.target = target; }
public void save() {
System.out.println("开始事务...");
target.save();
System.out.println("提交事务...");
}
} /**
* Test class
*/
public class App {
public static void main(String[] args) {
UserDao target = new UserDao();
UserDaoProxy proxy = new UserDaoProxy(target);
proxy.save();
}
}Static proxies are simple but generate many proxy classes and require updates when the interface changes.
Dynamic Proxy (JDK proxy) eliminates the need for a separate proxy class; the proxy is generated at runtime using java.lang.reflect.Proxy . The required method is static Object newProxyInstance(ClassLoader loader, Class [] interfaces, InvocationHandler h) . The article provides a ProxyFactory that creates a proxy instance and an InvocationHandler that wraps method calls with transaction messages.
static Object newProxyInstance(ClassLoader loader, Class
[] interfaces, InvocationHandler h ) public class ProxyFactory {
private Object target;
public ProxyFactory(Object target) { this.target = target; }
public Object getProxyInstance() {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始事务2");
Object returnValue = method.invoke(target, args);
System.out.println("提交事务2");
return returnValue;
}
}
);
}
} public class App {
public static void main(String[] args) {
IUserDao target = new UserDao();
System.out.println(target.getClass());
IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
System.out.println(proxy.getClass());
proxy.save();
}
}Dynamic proxies require the target to implement an interface; otherwise they cannot be used.
Cglib Proxy solves the limitation by creating a subclass of the target class at runtime, allowing proxying of classes without interfaces. It uses the Enhancer class and implements MethodInterceptor to add behavior before and after method execution.
/**
* Target class without any interface
*/
public class UserDao {
public void save() {
System.out.println("----已经保存数据!----");
}
} public class ProxyFactory implements MethodInterceptor {
private Object target;
public ProxyFactory(Object target) { this.target = target; }
public Object getProxyInstance() {
Enhancer en = new Enhancer();
en.setSuperclass(target.getClass());
en.setCallback(this);
return en.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("开始事务...");
Object returnValue = method.invoke(target, args);
System.out.println("提交事务...");
return returnValue;
}
} public class App {
@Test
public void test(){
UserDao target = new UserDao();
UserDao proxy = (UserDao) new ProxyFactory(target).getProxyInstance();
proxy.save();
}
}In Spring AOP, JDK dynamic proxies are used when the bean implements interfaces; otherwise Cglib proxies are employed.
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.