本文目录导读:

我来为你详细介绍Java代理模式的案例编写,包含静态代理和动态代理两种实现方式。
代理模式基础结构
定义核心接口和实现类:
// 1. 抽象主题接口
public interface Subject {
void request(String param);
String process(String data);
}
// 2. 真实主题实现类
public class RealSubject implements Subject {
@Override
public void request(String param) {
System.out.println("RealSubject处理请求: " + param);
// 模拟业务处理
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public String process(String data) {
System.out.println("RealSubject处理数据: " + data);
return "Processed: " + data.toUpperCase();
}
}
静态代理实现
// 3. 静态代理类
public class StaticProxy implements Subject {
private Subject realSubject;
public StaticProxy() {
this.realSubject = new RealSubject();
}
// 前置增强
private void before() {
System.out.println("[静态代理] 前置处理:记录日志、开启事务等");
}
// 后置增强
private void after() {
System.out.println("[静态代理] 后置处理:提交事务、记录结果等");
}
@Override
public void request(String param) {
before();
try {
realSubject.request(param);
} catch (Exception e) {
System.out.println("[静态代理] 异常处理:" + e.getMessage());
} finally {
after();
}
}
@Override
public String process(String data) {
before();
String result = null;
try {
result = realSubject.process(data);
System.out.println("[静态代理] 处理结果: " + result);
} catch (Exception e) {
System.out.println("[静态代理] 异常处理:" + e.getMessage());
} finally {
after();
}
return result;
}
// 扩展功能:访问控制
public void secureRequest(String param, boolean hasPermission) {
if (!hasPermission) {
System.out.println("[静态代理] 访问被拒绝:无权限");
return;
}
request(param);
}
}
JDK动态代理实现
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 4. JDK动态代理处理器
public class DynamicProxyHandler implements InvocationHandler {
private Object target; // 目标对象
private String proxyName;
public DynamicProxyHandler(Object target) {
this.target = target;
this.proxyName = "DynamicProxy";
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("[" + proxyName + "] 代理方法: " + method.getName());
// 前置增强
before(method, args);
Object result = null;
try {
// 调用目标方法
result = method.invoke(target, args);
// 后置增强
after(method, result);
} catch (Exception e) {
// 异常增强
exception(method, e);
throw e;
}
return result;
}
private void before(Method method, Object[] args) {
System.out.println("[" + proxyName + "] 前置处理");
System.out.println("[" + proxyName + "] 参数: " + (args != null ? java.util.Arrays.toString(args) : "无"));
}
private void after(Method method, Object result) {
System.out.println("[" + proxyName + "] 后置处理");
if (result != null) {
System.out.println("[" + proxyName + "] 返回值: " + result);
}
}
private void exception(Method method, Exception e) {
System.out.println("[" + proxyName + "] 异常处理: " + e.getMessage());
}
// 创建代理对象
@SuppressWarnings("unchecked")
public static <T> T createProxy(T target) {
return (T) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new DynamicProxyHandler(target)
);
}
}
CGLIB动态代理实现(需要cglib依赖)
<!-- pom.xml 添加依赖 -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
// 5. CGLIB动态代理(可以代理没有接口的类)
public class CglibProxy implements MethodInterceptor {
private String proxyName;
public CglibProxy() {
this.proxyName = "CglibProxy";
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)
throws Throwable {
System.out.println("[" + proxyName + "] 开始执行: " + method.getName());
// 前置处理
long startTime = System.currentTimeMillis();
Object result = null;
try {
// 调用父类方法
result = proxy.invokeSuper(obj, args);
// 后置处理
long endTime = System.currentTimeMillis();
System.out.println("[" + proxyName + "] 执行耗时: " + (endTime - startTime) + "ms");
} catch (Exception e) {
System.out.println("[" + proxyName + "] 异常: " + e.getMessage());
throw e;
}
return result;
}
// 创建代理对象
@SuppressWarnings("unchecked")
public static <T> T createProxy(T target) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(new CglibProxy());
return (T) enhancer.create();
}
}
实际应用案例:数据库连接池代理
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
// 6. 数据库连接池代理
public class ConnectionPoolProxy {
private List<Connection> connectionPool = new ArrayList<>();
private static final int POOL_SIZE = 5;
private static final String URL = "jdbc:mysql://localhost:3306/test";
private static final String USER = "root";
private static final String PASSWORD = "password";
public ConnectionPoolProxy() {
initializePool();
}
private void initializePool() {
for (int i = 0; i < POOL_SIZE; i++) {
connectionPool.add(createRealConnection());
}
}
private Connection createRealConnection() {
try {
return DriverManager.getConnection(URL, USER, PASSWORD);
} catch (SQLException e) {
throw new RuntimeException("创建数据库连接失败", e);
}
}
// 获取代理连接
public Connection getConnection() {
if (connectionPool.isEmpty()) {
System.out.println("连接池为空,创建新连接");
return createConnectionProxy(createRealConnection());
}
Connection realConn = connectionPool.remove(0);
System.out.println("从连接池获取连接,剩余: " + connectionPool.size());
return createConnectionProxy(realConn);
}
// 创建连接的代理对象
private Connection createConnectionProxy(Connection realConnection) {
// 使用JDK动态代理创建Connection的代理
return (Connection) Proxy.newProxyInstance(
Connection.class.getClassLoader(),
new Class[]{Connection.class},
new ConnectionProxyHandler(realConnection)
);
}
// 连接代理处理器
private class ConnectionProxyHandler implements InvocationHandler {
private Connection realConnection;
private boolean closed = false;
public ConnectionProxyHandler(Connection realConnection) {
this.realConnection = realConnection;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
// 拦截close方法,将连接归还到连接池
if ("close".equals(methodName)) {
if (!closed) {
closed = true;
connectionPool.add(realConnection);
System.out.println("连接归还到连接池,当前池大小: " + connectionPool.size());
}
return null;
}
// 如果连接已关闭,拒绝其他操作
if (closed) {
throw new SQLException("连接已关闭");
}
// 执行实际方法
return method.invoke(realConnection, args);
}
}
}
测试代码
public class ProxyPatternTest {
public static void main(String[] args) {
System.out.println("========== 1. 静态代理测试 ==========");
testStaticProxy();
System.out.println("\n========== 2. JDK动态代理测试 ==========");
testDynamicProxy();
System.out.println("\n========== 3. CGLIB代理测试 ==========");
testCglibProxy();
}
// 测试静态代理
private static void testStaticProxy() {
StaticProxy proxy = new StaticProxy();
proxy.request("静态代理请求");
System.out.println("---");
proxy.secureRequest("需要权限的请求", true);
proxy.secureRequest("无权限请求", false);
}
// 测试JDK动态代理
private static void testDynamicProxy() {
RealSubject realSubject = new RealSubject();
Subject proxy = DynamicProxyHandler.createProxy(realSubject);
proxy.request("动态代理请求");
System.out.println("---");
String result = proxy.process("hello world");
System.out.println("最终结果: " + result);
}
// 测试CGLIB代理
private static void testCglibProxy() {
RealSubject realSubject = new RealSubject();
Subject proxy = CglibProxy.createProxy(realSubject);
proxy.request("CGLIB代理请求");
System.out.println("---");
String result = proxy.process("cglib test");
System.out.println("最终结果: " + result);
// 测试没有接口的类
SimpleClass simple = CglibProxy.createProxy(new SimpleClass());
simple.doSomething();
}
// 用于测试CGLIB的无接口类
static class SimpleClass {
public void doSomething() {
System.out.println("SimpleClass执行操作");
}
}
}
三种代理模式对比
| 特性 | 静态代理 | JDK动态代理 | CGLIB动态代理 |
|---|---|---|---|
| 实现方式 | 手动编写代理类 | 自动生成代理类 | 自动生成子类 |
| 是否需接口 | 是 | 是 | 否 |
| 性能 | 较好 | 一般 | 较好 |
| 灵活性 | 差 | 好 | 好 |
| 适用范围 | 简单场景 | 有接口的场景 | 无接口或需更高性能 |
最佳实践建议
-
选择依据:
- 有接口:优先使用JDK动态代理
- 无接口或需性能:使用CGLIB
- 简单场景:考虑静态代理
-
应用场景:
- AOP(面向切面编程)
- 事务管理
- 权限控制
- 日志记录
- 性能监控
- 延迟加载
-
注意事项:
- 动态代理的性能开销
- 代理对象的序列化问题
- 不要对final类使用CGLIB
- 注意代理链的顺序
这个案例涵盖了Java代理模式的主要实现方式,你可以根据实际需求选择合适的实现方案。