Java代理模式案例如何编写

wen java案例 24

本文目录导读:

Java代理模式案例如何编写

  1. 代理模式基础结构
  2. 静态代理实现
  3. JDK动态代理实现
  4. CGLIB动态代理实现(需要cglib依赖)
  5. 实际应用案例:数据库连接池代理
  6. 测试代码
  7. 三种代理模式对比
  8. 最佳实践建议

我来为你详细介绍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动态代理
实现方式 手动编写代理类 自动生成代理类 自动生成子类
是否需接口
性能 较好 一般 较好
灵活性
适用范围 简单场景 有接口的场景 无接口或需更高性能

最佳实践建议

  1. 选择依据

    • 有接口:优先使用JDK动态代理
    • 无接口或需性能:使用CGLIB
    • 简单场景:考虑静态代理
  2. 应用场景

    • AOP(面向切面编程)
    • 事务管理
    • 权限控制
    • 日志记录
    • 性能监控
    • 延迟加载
  3. 注意事项

    • 动态代理的性能开销
    • 代理对象的序列化问题
    • 不要对final类使用CGLIB
    • 注意代理链的顺序

这个案例涵盖了Java代理模式的主要实现方式,你可以根据实际需求选择合适的实现方案。

抱歉,评论功能暂时关闭!