Java案例怎么实现动态代理?

wen java案例 11

Java动态代理实现案例

动态代理是Java中非常重要的设计模式,允许在运行时动态创建代理对象,主要有两种实现方式:

Java案例怎么实现动态代理?

JDK动态代理(基于接口)

适用场景:目标类实现了接口

// 1. 定义接口
public interface UserService {
    void addUser(String name);
    void deleteUser(int id);
    String findUser(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 findUser(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;
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("[日志] 开始执行方法:" + method.getName());
        // 调用目标方法
        Object result = method.invoke(target, args);
        // 后置增强
        System.out.println("[日志] 方法执行完成:" + method.getName());
        return result;
    }
}
// 4. 使用动态代理
public class JDKProxyDemo {
    public static void main(String[] args) {
        // 创建目标对象
        UserService target = new UserServiceImpl();
        // 创建代理对象
        UserService proxy = (UserService) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),  // 类加载器
            target.getClass().getInterfaces(),   // 接口数组
            new LogInvocationHandler(target)     // 调用处理器
        );
        // 使用代理对象
        proxy.addUser("张三");
        proxy.deleteUser(1);
        String user = proxy.findUser(100);
        System.out.println("查询结果:" + user);
    }
}

CGLIB动态代理(基于继承)

适用场景:目标类没有实现接口,或需要对类进行代理

// 1. 添加依赖(Maven)
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>
// 2. 目标类(无需接口)
public class UserDao {
    public void addUser(String name) {
        System.out.println("添加用户:" + name);
    }
    public final void deleteUser(int id) {
        System.out.println("删除用户ID:" + id);
    }
}
// 3. 实现MethodInterceptor
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxyInterceptor implements MethodInterceptor {
    private Object target;
    public CglibProxyInterceptor(Object target) {
        this.target = target;
    }
    // 创建代理对象
    public Object getProxy() {
        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 {
        System.out.println("[CGLIB] 前置处理");
        // 调用目标方法
        Object result = method.invoke(target, args);
        System.out.println("[CGLIB] 后置处理");
        return result;
    }
}
// 4. 使用CGLIB代理
public class CglibProxyDemo {
    public static void main(String[] args) {
        // 创建目标对象
        UserDao target = new UserDao();
        // 创建代理
        CglibProxyInterceptor interceptor = new CglibProxyInterceptor(target);
        UserDao proxy = (UserDao) interceptor.getProxy();
        // 使用代理对象
        proxy.addUser("李四");
        // proxy.deleteUser(2); // 注意:final方法无法被代理
    }
}

通用动态代理工具类

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
 * 通用动态代理工具类
 */
public class DynamicProxyUtil {
    /**
     * JDK动态代理
     */
    @SuppressWarnings("unchecked")
    public static <T> T createJDKProxy(T target, ProxyHandler handler) {
        return (T) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    handler.before(method, args);
                    Object result = method.invoke(target, args);
                    handler.after(method, result);
                    return result;
                }
            }
        );
    }
    /**
     * 代理处理器接口
     */
    public interface ProxyHandler {
        default void before(Method method, Object[] args) {}
        default void after(Method method, Object result) {}
    }
}
// 使用示例
public class MainDemo {
    public static void main(String[] args) {
        // 创建目标对象
        UserService userService = new UserServiceImpl();
        // 创建代理
        UserService proxy = DynamicProxyUtil.createJDKProxy(userService, 
            new DynamicProxyUtil.ProxyHandler() {
                @Override
                public void before(Method method, Object[] args) {
                    System.out.println("通用前置处理");
                }
                @Override
                public void after(Method method, Object result) {
                    System.out.println("通用后置处理");
                }
            }
        );
        // 测试
        proxy.addUser("测试用户");
    }
}

实际应用场景示例:事务管理

// 事务注解
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Transactional {
}
// 事务代理实现
public class TransactionProxy {
    @SuppressWarnings("unchecked")
    public static <T> T createTransactionProxy(T target) {
        return (T) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            (proxy, method, args) -> {
                Transactional transactional = method.getAnnotation(Transactional.class);
                if (transactional != null) {
                    System.out.println("开启事务...");
                    try {
                        Object result = method.invoke(target, args);
                        System.out.println("提交事务...");
                        return result;
                    } catch (Exception e) {
                        System.out.println("回滚事务...");
                        throw e;
                    }
                } else {
                    return method.invoke(target, args);
                }
            }
        );
    }
}
// 使用
public class BusinessService {
    @Transactional
    public void doBusiness() {
        System.out.println("执行业务逻辑");
    }
    public void normalOperation() {
        System.out.println("普通操作,无需事务");
    }
}
特性 JDK动态代理 CGLIB动态代理
实现方式 基于接口 基于继承(生成子类)
性能 较低(反射调用) 较高(直接调用)
限制 必须有接口 final方法不能被代理
适用版本 JDK 1.3+ 需要引入cglib库

选择建议

  • 如果目标类有接口 → 优先使用JDK动态代理
  • 如果没有接口或需要代理类本身 → 使用CGLIB
  • Spring框架默认使用JDK动态代理,没有接口时自动切换CGLIB

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