Java动态代理案例代码

wen java案例 3

本文目录导读:

Java动态代理案例代码

  1. JDK动态代理(基于接口)
  2. CGLIB动态代理(基于继承)
  3. 实际应用案例:事务管理
  4. JDK动态代理 vs CGLIB动态代理
  5. 关键说明

我来为您提供Java动态代理的完整案例代码,包括JDK动态代理和CGLIB动态代理两种方式。

JDK动态代理(基于接口)

案例:日志记录代理

// 1. 定义业务接口
public interface UserService {
    void addUser(String name);
    void deleteUser(int id);
    String getUser(int id);
}
// 2. 实现业务接口
public class UserServiceImpl implements UserService {
    @Override
    public void addUser(String name) {
        System.out.println("添加用户: " + name);
    }
    @Override
    public void deleteUser(int id) {
        System.out.println("删除用户, ID: " + id);
    }
    @Override
    public String getUser(int id) {
        System.out.println("查询用户, ID: " + id);
        return "用户" + id;
    }
}
// 3. 实现InvocationHandler接口
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class LogInvocationHandler implements InvocationHandler {
    private Object target; // 目标对象
    public LogInvocationHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 前置增强
        System.out.println("======= 方法调用开始 =======");
        System.out.println("调用方法: " + method.getName());
        System.out.println("参数: " + Arrays.toString(args));
        // 调用目标方法
        Object result = method.invoke(target, args);
        // 后置增强
        System.out.println("返回结果: " + result);
        System.out.println("======= 方法调用结束 =======");
        return result;
    }
    // 创建代理对象的工厂方法
    public static Object createProxy(Object target) {
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            new LogInvocationHandler(target)
        );
    }
}
// 4. 测试代码
public class JdkProxyTest {
    public static void main(String[] args) {
        // 创建目标对象
        UserService userService = new UserServiceImpl();
        // 创建代理对象
        UserService proxy = (UserService) LogInvocationHandler.createProxy(userService);
        // 调用代理方法
        System.out.println("=== 测试添加用户 ===");
        proxy.addUser("张三");
        System.out.println("\n=== 测试删除用户 ===");
        proxy.deleteUser(1001);
        System.out.println("\n=== 测试查询用户 ===");
        String user = proxy.getUser(1002);
        System.out.println("最终结果: " + user);
    }
}

通用JDK动态代理工具类

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactory {
    public static <T> T getProxy(T target, ProxyInterceptor interceptor) {
        return (T) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            (proxy, method, args) -> {
                Object result = null;
                if (interceptor.before(proxy, method, args)) {
                    result = method.invoke(target, args);
                }
                interceptor.after(proxy, method, args, result);
                return result;
            }
        );
    }
    // 拦截器接口
    public interface ProxyInterceptor {
        default boolean before(Object proxy, Method method, Object[] args) {
            return true;
        }
        default void after(Object proxy, Method method, Object[] args, Object result) {
        }
    }
}
// 使用示例
public class GenericProxyDemo {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        // 创建带日志的代理
        UserService proxy = ProxyFactory.getProxy(userService, new ProxyFactory.ProxyInterceptor() {
            @Override
            public boolean before(Object proxy, Method method, Object[] args) {
                System.out.println("前置处理: " + method.getName());
                return true;
            }
            @Override
            public void after(Object proxy, Method method, Object[] args, Object result) {
                System.out.println("后置处理: " + method.getName() + " 结果=" + result);
            }
        });
        proxy.addUser("李四");
    }
}

CGLIB动态代理(基于继承)

// 需要引入cglib依赖
// <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;
// 1. 定义一个普通类(不需要实现接口)
class PaymentService {
    public void pay(double amount) {
        System.out.println("支付: " + amount + " 元");
    }
    public void refund(double amount) {
        System.out.println("退款: " + amount + " 元");
    }
    public final String getServiceName() {
        return "支付服务";
    }
}
// 2. 实现MethodInterceptor
class PaymentInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        // 前置处理
        System.out.println("=== 开始执行: " + method.getName() + " ===");
        System.out.println("参数: " + args[0]);
        // 调用目标方法
        Object result = proxy.invokeSuper(obj, args);
        // 后置处理
        System.out.println("=== 执行完成: " + method.getName() + " ===");
        return result;
    }
    // 创建代理对象
    public static <T> T createProxy(Class<T> targetClass) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(targetClass);
        enhancer.setCallback(new PaymentInterceptor());
        return (T) enhancer.create();
    }
}
// 3. 测试CGLIB代理
public class CglibProxyDemo {
    public static void main(String[] args) {
        // 创建代理对象
        PaymentService proxy = PaymentInterceptor.createProxy(PaymentService.class);
        // 调用代理方法
        proxy.pay(100.0);
        System.out.println();
        proxy.refund(50.0);
        // 注意:final方法不会被代理
        System.out.println("\n服务名称: " + proxy.getServiceName());
    }
}

实际应用案例:事务管理

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 定义一个简单的数据库事务管理器
class TransactionManager {
    public void beginTransaction() {
        System.out.println("开始事务...");
    }
    public void commitTransaction() {
        System.out.println("提交事务...");
    }
    public void rollbackTransaction(Exception e) {
        System.out.println("回滚事务, 异常: " + e.getMessage());
    }
}
// 业务接口
interface AccountService {
    void transfer(String from, String to, double amount);
}
// 业务实现类
class AccountServiceImpl implements AccountService {
    @Override
    public void transfer(String from, String to, double amount) {
        System.out.println("从账户[" + from + "]转账给[" + to + "]金额[" + amount + "]成功");
        // 模拟业务处理
        // 如果金额大于10000,抛出异常模拟失败场景
        if (amount > 10000) {
            throw new RuntimeException("转账金额超限");
        }
    }
}
// 事务代理
public class TransactionProxy {
    public static <T> T getTransactionProxy(T target) {
        return (T) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            (proxy, method, args) -> {
                TransactionManager tx = new TransactionManager();
                Object result = null;
                try {
                    tx.beginTransaction();
                    result = method.invoke(target, args);
                    tx.commitTransaction();
                } catch (Exception e) {
                    tx.rollbackTransaction(e);
                    throw e;
                }
                return result;
            }
        );
    }
    public static void main(String[] args) {
        // 创建原始对象
        AccountService accountService = new AccountServiceImpl();
        // 创建带事务的代理
        AccountService proxy = getTransactionProxy(accountService);
        // 测试成功场景
        System.out.println("=== 测试正常转账 ===");
        proxy.transfer("A账户", "B账户", 5000);
        // 测试失败场景
        System.out.println("\n=== 测试异常转账 ===");
        try {
            proxy.transfer("A账户", "B账户", 15000);
        } catch (RuntimeException e) {
            System.out.println("转账失败: " + e.getMessage());
        }
    }
}

JDK动态代理 vs CGLIB动态代理

public class ProxyComparison {
    public static void main(String[] args) {
        // JDK代理(接口代理)
        System.out.println("=== JDK动态代理 ===");
        UserService userService = new UserServiceImpl();
        UserService jdkProxy = (UserService) LogInvocationHandler.createProxy(userService);
        jdkProxy.addUser("测试JDK代理");
        // CGLIB代理(类代理)
        System.out.println("\n=== CGLIB动态代理 ===");
        PaymentService cglibProxy = PaymentInterceptor.createProxy(PaymentService.class);
        cglibProxy.pay(100);
        // 关键区别
        System.out.println("\n=== 关键区别 ===");
        System.out.println("1. JDK代理: 基于接口实现,需要目标类实现接口");
        System.out.println("2. CGLIB代理: 基于继承实现,可以代理普通类");
        System.out.println("3. JDK代理: 使用java.lang.reflect.Proxy");
        System.out.println("4. CGLIB代理: 使用net.sf.cglib.proxy.Enhancer");
        System.out.println("5. JDK代理: 性能较高(JDK8+)");
        System.out.println("6. CGLIB代理: 不能代理final类和方法");
    }
}

关键说明

执行流程

  1. JDK动态代理流程

    • 创建目标对象
    • 创建InvocationHandler实例
    • 使用Proxy.newProxyInstance创建代理对象
    • 调用代理对象的方法时,会调用InvocationHandler的invoke方法
  2. CGLIB动态代理流程

    • 创建Enhancer实例
    • 设置父类(目标类)
    • 设置MethodInterceptor回调
    • 创建代理对象

使用场景

  • JDK动态代理:目标类实现接口时使用;Spring等框架的默认实现
  • CGLIB动态代理:目标类没有实现接口时使用;MyBatis-Spring等需要代理类的场景

选择建议

  1. 优先使用JDK代理,因为它更简单、性能更好
  2. 当目标类没有实现接口时,使用CGLIB代理
  3. 注意CGLIB不能代理final类和方法

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