本文目录导读:

我将为您详细介绍Java代理模式的几种实现方式,并给出完整的案例代码。
代理模式概述
代理模式(Proxy Pattern)为其他对象提供一种代理以控制对这个对象的访问,它属于结构型设计模式。
代理模式的主要类型:
- 静态代理:在编译时确定代理类
- 动态代理(JDK):基于接口的代理
- CGLIB代理:基于继承的代理
完整案例代码
1 定义接口和真实主题
// 业务接口
public interface UserService {
void addUser(String name);
void deleteUser(String name);
String getUser(String name);
}
// 真实主题类
public class UserServiceImpl implements UserService {
@Override
public void addUser(String name) {
// 模拟业务处理
System.out.println("添加用户:" + name);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void deleteUser(String name) {
System.out.println("删除用户:" + name);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public String getUser(String name) {
System.out.println("查询用户:" + name);
return name + "的信息";
}
}
2 静态代理实现
// 静态代理类
public class StaticProxy implements UserService {
private final UserService target;
public StaticProxy(UserService target) {
this.target = target;
}
@Override
public void addUser(String name) {
System.out.println("【静态代理】-开始执行添加用户操作...");
long startTime = System.currentTimeMillis();
// 调用真实对象的方法
target.addUser(name);
long endTime = System.currentTimeMillis();
System.out.println("【静态代理】-添加用户操作完成,耗时:" + (endTime - startTime) + "ms");
}
@Override
public void deleteUser(String name) {
System.out.println("【静态代理】-开始执行删除用户操作...");
long startTime = System.currentTimeMillis();
target.deleteUser(name);
long endTime = System.currentTimeMillis();
System.out.println("【静态代理】-删除用户操作完成,耗时:" + (endTime - startTime) + "ms");
}
@Override
public String getUser(String name) {
System.out.println("【静态代理】-开始执行查询用户操作...");
long startTime = System.currentTimeMillis();
String result = target.getUser(name);
long endTime = System.currentTimeMillis();
System.out.println("【静态代理】-查询用户操作完成,耗时:" + (endTime - startTime) + "ms");
return result;
}
}
3 JDK动态代理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 动态代理类
public class DynamicProxy implements InvocationHandler {
private final Object target;
public DynamicProxy(Object target) {
this.target = target;
}
// 创建代理对象
public Object createProxy() {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this
);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
System.out.println("【JDK动态代理】-" + methodName + "方法开始执行...");
long startTime = System.currentTimeMillis();
// 执行前置处理
if (args != null && args.length > 0) {
System.out.println("【JDK动态代理】-参数:");
for (Object arg : args) {
System.out.println(" " + arg);
}
}
// 调用真实对象的方法
Object result = method.invoke(target, args);
long endTime = System.currentTimeMillis();
System.out.println("【JDK动态代理】-" + methodName + "方法执行完成,耗时:" + (endTime - startTime) + "ms");
return result;
}
}
4 CGLIB代理
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
// CGLIB代理类
public class CGLIBProxy implements MethodInterceptor {
private final Object target;
public CGLIBProxy(Object target) {
this.target = target;
}
// 创建代理对象
public Object createProxy() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)
throws Throwable {
String methodName = method.getName();
System.out.println("【CGLIB代理】-" + methodName + "方法开始执行...");
long startTime = System.currentTimeMillis();
// 前置处理
if (args != null && args.length > 0) {
System.out.println("【CGLIB代理】-参数:" + String.join(", ",
java.util.Arrays.stream(args).map(String::valueOf).toArray(String[]::new)));
}
// 调用真实对象的方法
Object result = proxy.invoke(target, args);
long endTime = System.currentTimeMillis();
System.out.println("【CGLIB代理】-" + methodName + "方法执行完成,耗时:" + (endTime - startTime) + "ms");
return result;
}
}
5 主测试类
public class ProxyPatternDemo {
public static void main(String[] args) {
System.out.println("========== 代理模式案例演示 ==========\n");
// 创建真实对象
UserService userService = new UserServiceImpl();
// 1. 静态代理测试
System.out.println("----- 1. 静态代理 -----");
UserService staticProxy = new StaticProxy(userService);
staticProxy.addUser("张三");
staticProxy.deleteUser("张三");
System.out.println();
// 2. JDK动态代理测试
System.out.println("----- 2. JDK动态代理 -----");
DynamicProxy dynamicProxyHandler = new DynamicProxy(userService);
UserService dynamicProxy = (UserService) dynamicProxyHandler.createProxy();
dynamicProxy.addUser("李四");
String userInfo = dynamicProxy.getUser("李四");
System.out.println("查询结果:" + userInfo);
System.out.println();
// 3. CGLIB代理测试
System.out.println("----- 3. CGLIB代理 -----");
CGLIBProxy cglibProxyHandler = new CGLIBProxy(userService);
UserServiceImpl cglibProxy = (UserServiceImpl) cglibProxyHandler.createProxy();
cglibProxy.addUser("王五");
cglibProxy.deleteUser("王五");
System.out.println();
// 4. 对比不同代理方式
compareProxies();
}
private static void compareProxies() {
System.out.println("----- 代理方式对比 -----");
System.out.println("1. 静态代理:简单直观,但每个类都需要手动创建代理类,代码重复");
System.out.println("2. JDK动态代理:基于接口,代码复用性好,但只能代理接口");
System.out.println("3. CGLIB代理:基于继承,无需接口,但性能略低于JDK代理");
}
}
6 使用场景扩展(权限控制示例)
// 权限控制的代理示例
public class PermissionProxy implements UserService {
private final UserService target;
private String currentUserRole;
public PermissionProxy(UserService target, String role) {
this.target = target;
this.currentUserRole = role;
}
@Override
public void addUser(String name) {
if ("admin".equals(currentUserRole)) {
System.out.println("【权限代理】-管理员权限验证通过,执行添加操作");
target.addUser(name);
} else {
System.out.println("【权限代理】-权限不足,无法添加用户(需要管理员权限)");
}
}
@Override
public void deleteUser(String name) {
if ("admin".equals(currentUserRole)) {
System.out.println("【权限代理】-管理员权限验证通过,执行删除操作");
target.deleteUser(name);
} else {
System.out.println("【权限代理】-权限不足,无法删除用户(需要管理员权限)");
}
}
@Override
public String getUser(String name) {
// 查询操作所有人都有权限
System.out.println("【权限代理】-权限验证通过(查询操作对所有用户开放)");
return target.getUser(name);
}
}
运行结果
========== 代理模式案例演示 ==========
----- 1. 静态代理 -----
【静态代理】-开始执行添加用户操作...
添加用户:张三
【静态代理】-添加用户操作完成,耗时:500ms
【静态代理】-开始执行删除用户操作...
删除用户:张三
【静态代理】-删除用户操作完成,耗时:300ms
----- 2. JDK动态代理 -----
【JDK动态代理】-addUser方法开始执行...
【JDK动态代理】-参数:
李四
添加用户:李四
【JDK动态代理】-addUser方法执行完成,耗时:500ms
【JDK动态代理】-getUser方法开始执行...
【JDK动态代理】-参数:
李四
查询用户:李四
【JDK动态代理】-getUser方法执行完成,耗时:0ms
查询结果:李四的信息
----- 3. CGLIB代理 -----
【CGLIB代理】-addUser方法开始执行...
【CGLIB代理】-参数:王五
添加用户:王五
【CGLIB代理】-addUser方法执行完成,耗时:500ms
【CGLIB代理】-deleteUser方法开始执行...
【CGLIB代理】-参数:王五
删除用户:王五
【CGLIB代理】-deleteUser方法执行完成,耗时:300ms
----- 代理方式对比 -----
1. 静态代理:简单直观,但每个类都需要手动创建代理类,代码重复
2. JDK动态代理:基于接口,代码复用性好,但只能代理接口
3. CGLIB代理:基于继承,无需接口,但性能略低于JDK代理
代理模式的优势和应用场景
优势:
- 职责清晰:代理类负责预处理、过滤等操作
- 扩展性好:可以在不修改目标类的情况下增加功能
- 安全性好:可以控制对目标对象的访问权限
典型应用场景:
- Spring AOP:事务管理、日志记录
- Spring MVC:拦截器
- MyBatis:Mapper接口的动态代理
- Hibernate:延迟加载
- Java RMI:远程方法调用
- 安全控制:权限验证、身份认证
注意事项:
- 静态代理类需要手动编写,会产生大量冗余代码
- JDK代理要求目标类必须实现接口
- CGLIB代理不能代理final类和方法