Java代理模式
代理模式为对象提供代理,控制对其访问。
模式定义
意图:为对象提供代理,控制访问或添加功能。
三种代理类型
| 类型 | 特点 | 实现方式 |
|---|---|---|
| 静态代理 | 手写代理类 | 继承/组合 |
| JDK动态代理 | 基于接口 | Proxy类 |
| CGLIB代理 | 基于类 | 字节码生成 |
静态代理
接口定义
Java
public interface UserService {
void addUser(String name);
void deleteUser(String name);
}
目标对象
Java
public class UserServiceImpl implements UserService {
@Override
public void addUser(String name) {
System.out.println("添加用户: " + name);
}
@Override
public void deleteUser(String name) {
System.out.println("删除用户: " + name);
}
}
静态代理
Java
public class UserServiceProxy implements UserService {
private UserService target;
public UserServiceProxy(UserService target) {
this.target = target;
}
@Override
public void addUser(String name) {
System.out.println("前置处理:检查权限");
target.addUser(name);
System.out.println("后置处理:记录日志");
}
@Override
public void deleteUser(String name) {
System.out.println("前置处理:检查权限");
target.deleteUser(name);
System.out.println("后置处理:记录日志");
}
}
// 使用
UserService service = new UserServiceProxy(new UserServiceImpl());
service.addUser("张三");
JDK动态代理
Java
public class JdkProxy implements InvocationHandler {
private Object target;
public Object bind(Object target) {
this.target = target;
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this
);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前置处理");
Object result = method.invoke(target, args);
System.out.println("后置处理");
return result;
}
}
// 使用
UserService service = (UserService) new JdkProxy()
.bind(new UserServiceImpl());
service.addUser("张三");
CGLIB代理
Java
public class CglibProxy implements MethodInterceptor {
public Object getProxy(Class<?> clazz) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("前置处理");
Object result = proxy.invokeSuper(obj, args);
System.out.println("后置处理");
return result;
}
}
// 使用(无需接口)
UserServiceImpl service = (UserServiceImpl) new CglibProxy()
.getProxy(UserServiceImpl.class);
service.addUser("张三");
JDK代理 vs CGLIB代理
| 特性 | JDK代理 | CGLIB代理 |
|---|---|---|
| 基础 | 接口 | 类 |
| 限制 | 必须有接口 | 不能代理final类 |
| 性能 | 较低 | 较高 |
| Spring默认 | 有接口用JDK | 无接口用CGLIB |
实际应用示例
远程代理
Java
public class RemoteProxy implements Service {
private String host;
private int port;
@Override
public void execute() {
// 通过网络调用远程服务
Socket socket = new Socket(host, port);
// 发送请求、接收响应...
}
}
虚拟代理
Java
public class ImageProxy implements Image {
private RealImage realImage;
private String filename;
public ImageProxy(String filename) {
this.filename = filename;
}
@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(filename); // 延迟加载
}
realImage.display();
}
}
保护代理
Java
public class ProtectionProxy implements Service {
private RealService realService;
private User user;
@Override
public void operation() {
if (user.hasPermission()) {
realService.operation();
} else {
throw new SecurityException("无权限");
}
}
}
Spring AOP代理
Java
@Aspect
@Component
public class LogAspect {
@Before("execution(* com.example.service.*.*(..))")
public void before(JoinPoint joinPoint) {
System.out.println("方法执行前: " + joinPoint.getSignature());
}
@After("execution(* com.example.service.*.*(..))")
public void after(JoinPoint joinPoint) {
System.out.println("方法执行后");
}
}
适用场景
- 远程代理(RPC)
- 虚拟代理(延迟加载)
- 保护代理(权限控制)
- 智能代理(添加逻辑)
- AOP实现
注意事项
JDK动态代理要求目标类有接口
CGLIB不能代理final类和方法
代理类应保持与目标类相同接口
Spring会根据情况自动选择代理方式
要点总结
- 代理模式控制对象访问,可添加额外逻辑
- 静态代理手写代理类,不够灵活
- JDK动态代理基于接口,Proxy.newProxyInstance()
- CGLIB基于类继承,无接口也能代理
- Spring AOP是代理模式的典型应用
📝 发现内容有误?点击此处直接编辑