Java动态代理案例如何实现

wen java案例 28

Java动态代理案例实现

动态代理是Java中非常重要的特性,主要用于在不修改原有代码的情况下增强方法的功能,以下是完整的实现案例:

Java动态代理案例如何实现

核心接口和实现类

// 1. 定义业务接口
public interface UserService {
    void addUser(String username);
    void deleteUser(int id);
    String getUser(int id);
}
// 2. 实现类
public class UserServiceImpl implements UserService {
    @Override
    public void addUser(String username) {
        System.out.println("添加用户: " + username);
    }
    @Override
    public void deleteUser(int id) {
        System.out.println("删除用户: " + id);
    }
    @Override
    public String getUser(int id) {
        System.out.println("获取用户: " + id);
        return "User_" + id;
    }
}

JDK动态代理实现

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 3. 实现InvocationHandler接口
public class LogProxyHandler implements InvocationHandler {
    // 目标对象
    private Object target;
    public LogProxyHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 前置增强
        System.out.println("===== 开始执行方法: " + method.getName() + " =====");
        // 记录参数
        if (args != null && args.length > 0) {
            System.out.print("参数: ");
            for (Object arg : args) {
                System.out.print(arg + " ");
            }
            System.out.println();
        }
        long startTime = System.currentTimeMillis();
        // 调用目标方法
        Object result = method.invoke(target, args);
        long endTime = System.currentTimeMillis();
        // 后置增强
        System.out.println("执行耗时: " + (endTime - startTime) + "ms");
        System.out.println("===== 结束执行方法: " + method.getName() + " =====\n");
        return result;
    }
    // 获取代理对象
    public Object getProxy() {
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            this
        );
    }
}

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,需要导入cglib依赖
public class CglibProxyHandler implements MethodInterceptor {
    private Object target;
    public CglibProxyHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) 
            throws Throwable {
        // 前置处理
        System.out.println("CGLIB代理 - 方法执行前: " + method.getName());
        // 调用目标方法
        Object result = method.invoke(target, args);
        // 后置处理
        System.out.println("CGLIB代理 - 方法执行后: " + method.getName());
        return result;
    }
    // 获取代理对象
    public Object getProxy() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }
}

测试代码

public class ProxyDemo {
    public static void main(String[] args) {
        // 创建目标对象
        UserService userService = new UserServiceImpl();
        // JDK动态代理测试
        System.out.println("========== JDK动态代理 ==========");
        LogProxyHandler handler = new LogProxyHandler(userService);
        UserService proxyService = (UserService) handler.getProxy();
        // 通过代理对象调用方法
        proxyService.addUser("张三");
        proxyService.deleteUser(1001);
        String user = proxyService.getUser(1001);
        System.out.println("返回结果: " + user);
        // CGLIB动态代理测试
        System.out.println("\n========== CGLIB动态代理 ==========");
        CglibProxyHandler cglibHandler = new CglibProxyHandler(userService);
        UserService cglibProxy = (UserService) cglibHandler.getProxy();
        cglibProxy.addUser("李四");
    }
}

更实用的事务代理示例

import java.sql.Connection;
public class TransactionProxy implements InvocationHandler {
    private Object target;
    private Connection connection;
    public TransactionProxy(Object target, Connection connection) {
        this.target = target;
        this.connection = connection;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        try {
            // 开启事务
            connection.setAutoCommit(false);
            System.out.println("开启事务");
            // 执行目标方法
            result = method.invoke(target, args);
            // 提交事务
            connection.commit();
            System.out.println("提交事务");
        } catch (Exception e) {
            // 回滚事务
            connection.rollback();
            System.out.println("回滚事务");
            throw e;
        } finally {
            connection.setAutoCommit(true);
        }
        return result;
    }
    public Object getProxy() {
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            this
        );
    }
}

Maven依赖(如果使用CGLIB)

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

关键点说明

  1. JDK动态代理

    • 必须实现接口
    • 使用java.lang.reflect.Proxy
    • 性能较好,原生支持
  2. CGLIB动态代理

    • 不需要实现接口
    • 通过继承目标类实现
    • 不能代理final类和方法
  3. 应用场景

    • 日志记录
    • 事务管理
    • 权限控制
    • 性能监控
    • AOP编程
  4. 注意事项

    • JDK代理只能代理接口方法
    • CGLIB不能代理final方法
    • 代理对象的equals、hashCode、toString方法会被特殊处理

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