← 返回首页

Java代理模式详解

📂 java ⏱ 3 min 516 words

Java代理模式详解

什么是代理模式

代理模式为目标对象提供一个代理对象,通过代理对象控制对目标对象的访问。在Java中广泛应用于AOP、RPC、ORM等框架。

静态代理

public interface UserService {
    void addUser(String name);
    String getUser(int id);
}

public class UserServiceImpl implements UserService {
    @Override
    public void addUser(String name) {
        System.out.println("添加用户: " + name);
    }

    @Override
    public String getUser(int id) {
        return "用户" + id;
    }
}

public class UserServiceProxy implements UserService {
    private UserService target;

    public UserServiceProxy(UserService target) {
        this.target = target;
    }

    @Override
    public void addUser(String name) {
        long start = System.currentTimeMillis();
        target.addUser(name);
        long cost = System.currentTimeMillis() - start;
        System.out.println("耗时: " + cost + "ms");
    }

    @Override
    public String getUser(int id) {
        long start = System.currentTimeMillis();
        String result = target.getUser(id);
        long cost = System.currentTimeMillis() - start;
        System.out.println("耗时: " + cost + "ms");
        return result;
    }
}

// 使用
UserService service = new UserServiceProxy(new UserServiceImpl());
service.addUser("张三");

JDK动态代理

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JdkProxyHandler implements InvocationHandler {
    private Object target;

    public JdkProxyHandler(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());

        long start = System.nanoTime();
        Object result = method.invoke(target, args);
        long cost = (System.nanoTime() - start) / 1000;

        System.out.println("方法耗时: " + cost + "μs");
        System.out.println("=== 后置增强 ===");
        return result;
    }

    public static <T> T createProxy(T target) {
        return (T) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            new JdkProxyHandler(target)
        );
    }
}

// 使用
UserService realService = new UserServiceImpl();
UserService proxyService = JdkProxyHandler.createProxy(realService);
proxyService.addUser("张三");

CGLIB代理

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibInterceptor implements MethodInterceptor {
    private Object target;

    public CglibInterceptor(Object target) {
        this.target = target;
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args,
                            MethodProxy methodProxy) throws Throwable {
        System.out.println("=== CGLIB前置增强 ===");

        long start = System.nanoTime();
        Object result = methodProxy.invokeSuper(obj, args);
        long cost = (System.nanoTime() - start) / 1000;

        System.out.println("方法耗时: " + cost + "μs");
        System.out.println("=== CGLIB后置增强 ===");
        return result;
    }

    public static <T> T createProxy(T target) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(new CglibInterceptor(target));
        return (T) enhancer.create();
    }
}

// 使用
UserServiceImpl service = CglibInterceptor.createProxy(new UserServiceImpl());
service.addUser("张三");

JDK代理 vs CGLIB代理

特性 JDK动态代理 CGLIB代理
实现方式 基于接口 基于继承
要求 目标类必须实现接口 目标类不能是final
性能 反射调用,略慢 字节码生成,较快
适用场景 接口代理 类代理

Spring AOP中的代理

// Spring默认策略:
// 1. 目标类实现了接口 → JDK动态代理
// 2. 目标类没有实现接口 → CGLIB代理
// 3. 强制使用CGLIB:@EnableAspectJAutoProxy(proxyTargetClass = true)

@Service
public class OrderService {
    @Transactional
    public void createOrder(Order order) {
        // Spring通过代理管理事务
        orderRepository.save(order);
    }
}

// 自定义AOP代理
@Aspect
@Component
public class LogAspect {
    @Around("execution(* com.example.service.*.*(..))")
    public Object logMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("调用: " + joinPoint.getSignature());
        long start = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        System.out.println("耗时: " + (System.currentTimeMillis() - start) + "ms");
        return result;
    }
}

动态代理实现方法拦截器

public interface Interceptor {
    Object intercept(Invocation invocation) throws Throwable;
}

public class Invocation {
    private Object target;
    private Method method;
    private Object[] args;

    public Object proceed() throws Throwable {
        return method.invoke(target, args);
    }
}

public class LoggingInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("[LOG] " + invocation.getMethod().getName());
        return invocation.proceed();
    }
}

public class PerformanceInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        long start = System.nanoTime();
        Object result = invocation.proceed();
        System.out.println("[PERF] " + invocation.getMethod().getName()
            + " took " + (System.nanoTime() - start) + "ns");
        return result;
    }
}

总结

代理模式是Java中最重要的设计模式之一。JDK动态代理基于接口,CGLIB基于继承。Spring AOP默认使用JDK代理,可通过配置切换为CGLIB。