Java代理模式详解
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。