1. 项目结构
bash
proxy-pattern-demo/
├── pom.xml
├── src/
│ └── main/
│ └── java/
│ └── com/
│ └── demo/
│ ├── proxy/
│ │ ├── Image.java
│ │ ├── RealImage.java
│ │ ├── ImageProxy.java
│ │ └── ProtectionProxy/
│ │ ├── Document.java
│ │ ├── RealDocument.java
│ │ ├── DocumentProxy.java
│ │ └── UserRole.java
│ ├── dynamic/
│ │ ├── UserService.java
│ │ ├── UserServiceImpl.java
│ │ ├── LoggingInvocationHandler.java
│ │ └── CacheInvocationHandler.java
│ └── App.java
Maven 配置文件 (pom.xml)
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>proxy-pattern-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
2. 代码实现
-
静态代理示例:
Image.java (接口)javapackage com.demo.proxy; public interface Image { void display(); String getFileName(); }RealImage.java (真实对象)
javapackage com.demo.proxy; import lombok.AllArgsConstructor; import lombok.Data; @Data @AllArgsConstructor public class RealImage implements Image { private String fileName; public RealImage(String fileName) { this.fileName = fileName; loadFromDisk(); } private void loadFromDisk() { System.out.println("正在从磁盘加载图片: " + fileName); // 模拟耗时操作 try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } @Override public void display() { System.out.println("显示图片: " + fileName); } }ImageProxy.java (代理类)
javapackage com.demo.proxy; import lombok.Data; @Data 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(); } @Override public String getFileName() { return fileName; } // 代理的额外功能 public void showImageInfo() { System.out.println("图片代理信息: " + fileName); System.out.println("真实对象是否已加载: " + (realImage != null)); } } -
保护代理示例
UserRole.java (用户角色枚举)javapackage com.demo.proxy.ProtectionProxy; public enum UserRole { GUEST, USER, ADMIN }Document.java (接口)
javapackage com.demo.proxy.ProtectionProxy; public interface Document { void view(); void edit(); void delete(); String getContent(); }RealDocument.java (真实文档)
javapackage com.demo.proxy.ProtectionProxy; import lombok.AllArgsConstructor; import lombok.Data; @Data @AllArgsConstructor public class RealDocument implements Document { private String content; private String author; @Override public void view() { System.out.println("查看文档内容: " + content); } @Override public void edit() { System.out.println("编辑文档: " + content); } @Override public void delete() { System.out.println("删除文档: " + content); } @Override public String getContent() { return content; } }DocumentProxy.java (保护代理)
javapackage com.demo.proxy.ProtectionProxy; import lombok.AllArgsConstructor; import lombok.Data; @Data @AllArgsConstructor public class DocumentProxy implements Document { private RealDocument realDocument; private UserRole userRole; public DocumentProxy(String content, String author, UserRole userRole) { this.realDocument = new RealDocument(content, author); this.userRole = userRole; } @Override public void view() { // 所有角色都可以查看 System.out.println("[" + userRole + "] 请求查看文档"); realDocument.view(); } @Override public void edit() { // 只有USER和ADMIN可以编辑 if (userRole == UserRole.USER || userRole == UserRole.ADMIN) { System.out.println("[" + userRole + "] 请求编辑文档"); realDocument.edit(); } else { System.out.println("[" + userRole + "] 没有编辑权限"); } } @Override public void delete() { // 只有ADMIN可以删除 if (userRole == UserRole.ADMIN) { System.out.println("[" + userRole + "] 请求删除文档"); realDocument.delete(); } else { System.out.println("[" + userRole + "] 没有删除权限"); } } @Override public String getContent() { return realDocument.getContent(); } } -
动态代理示例
UserService.java (接口)javapackage com.demo.dynamic; public interface UserService { String getUserInfo(int userId); void updateUserInfo(int userId, String info); int getUserCount(); }UserServiceImpl.java (实现类)
javapackage com.demo.dynamic; import lombok.extern.slf4j.Slf4j; @Slf4j public class UserServiceImpl implements UserService { @Override public String getUserInfo(int userId) { log.info("获取用户信息: {}", userId); // 模拟数据库查询 try { Thread.sleep(500); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return "用户" + userId + "的信息"; } @Override public void updateUserInfo(int userId, String info) { log.info("更新用户信息: {} -> {}", userId, info); // 模拟数据库更新 try { Thread.sleep(800); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } @Override public int getUserCount() { log.info("获取用户总数"); return 100; } }LoggingInvocationHandler.java (日志增强处理器)
javapackage com.demo.dynamic; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Date; public class LoggingInvocationHandler implements InvocationHandler { private final Object target; public LoggingInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long startTime = System.currentTimeMillis(); System.out.println("[" + new Date() + "] 开始调用方法: " + method.getName()); System.out.println("方法参数: " + (args != null ? Arrays.toString(args) : "无")); try { Object result = method.invoke(target, args); long endTime = System.currentTimeMillis(); System.out.println("[" + new Date() + "] 方法调用完成: " + method.getName()); System.out.println("执行时间: " + (endTime - startTime) + "ms"); System.out.println("返回结果: " + result); return result; } catch (Exception e) { System.out.println("方法调用异常: " + e.getMessage()); throw e; } } }CacheInvocationHandler.java (缓存增强处理器)
javapackage com.demo.dynamic; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; public class CacheInvocationHandler implements InvocationHandler { private final Object target; private final Map<String, Object> cache = new HashMap<>(); public CacheInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 只缓存getUserInfo方法 if ("getUserInfo".equals(method.getName()) && args != null && args.length == 1) { String cacheKey = method.getName() + "_" + args[0]; if (cache.containsKey(cacheKey)) { System.out.println("从缓存获取数据: " + cacheKey); return cache.get(cacheKey); } Object result = method.invoke(target, args); cache.put(cacheKey, result); System.out.println("将数据存入缓存: " + cacheKey); return result; } return method.invoke(target, args); } }
主程序 App.java
java
package com.demo;
import com.demo.proxy.Image;
import com.demo.proxy.ImageProxy;
import com.demo.proxy.ProtectionProxy.Document;
import com.demo.proxy.ProtectionProxy.DocumentProxy;
import com.demo.proxy.ProtectionProxy.UserRole;
import com.demo.dynamic.UserService;
import com.demo.dynamic.UserServiceImpl;
import com.demo.dynamic.LoggingInvocationHandler;
import com.demo.dynamic.CacheInvocationHandler;
import java.lang.reflect.Proxy;
public class App {
public static void main(String[] args) {
System.out.println("========== 代理模式演示 ==========\n");
// 1. 静态代理演示 - 虚拟代理
System.out.println("1. 静态代理演示 - 虚拟代理");
System.out.println("---------------------------");
Image image = new ImageProxy("test.jpg");
// 第一次调用会加载真实对象
System.out.println("第一次调用display():");
image.display();
System.out.println();
// 第二次调用直接使用已加载的对象
System.out.println("第二次调用display():");
image.display();
System.out.println();
// 2. 保护代理演示
System.out.println("2. 保护代理演示");
System.out.println("---------------------------");
// 不同角色的访问权限
UserRole[] roles = {UserRole.GUEST, UserRole.USER, UserRole.ADMIN};
for (UserRole role : roles) {
System.out.println("\n--- " + role + " 角色操作 ---");
Document doc = new DocumentProxy("机密文档内容", "admin", role);
doc.view();
doc.edit();
doc.delete();
}
System.out.println();
// 3. 动态代理演示
System.out.println("3. 动态代理演示");
System.out.println("---------------------------");
UserService userService = new UserServiceImpl();
// 创建日志代理
UserService loggingProxy = (UserService) Proxy.newProxyInstance(
UserService.class.getClassLoader(),
new Class[]{UserService.class},
new LoggingInvocationHandler(userService)
);
System.out.println("\n--- 日志代理测试 ---");
loggingProxy.getUserInfo(1);
loggingProxy.updateUserInfo(1, "新信息");
// 创建缓存代理
UserService cacheProxy = (UserService) Proxy.newProxyInstance(
UserService.class.getClassLoader(),
new Class[]{UserService.class},
new CacheInvocationHandler(userService)
);
System.out.println("\n--- 缓存代理测试 ---");
System.out.println("第一次调用getUserInfo(1):");
cacheProxy.getUserInfo(1);
System.out.println("\n第二次调用getUserInfo(1):");
cacheProxy.getUserInfo(1);
System.out.println("\n调用getUserInfo(2):");
cacheProxy.getUserInfo(2);
// 4. 组合代理 (代理链)
System.out.println("\n--- 代理链测试 (日志 + 缓存) ---");
UserService chainProxy = (UserService) Proxy.newProxyInstance(
UserService.class.getClassLoader(),
new Class[]{UserService.class},
new CacheInvocationHandler(
(UserService) Proxy.newProxyInstance(
UserService.class.getClassLoader(),
new Class[]{UserService.class},
new LoggingInvocationHandler(userService)
)
)
);
System.out.println("\n第一次调用getUserInfo(3):");
chainProxy.getUserInfo(3);
System.out.println("\n第二次调用getUserInfo(3):");
chainProxy.getUserInfo(3);
System.out.println("\n========== 演示结束 ==========");
}
}
3. 构建和运行
-
编译项目
bashmvn clean compile -
运行项目
bashmvn exec:java -Dexec.mainClass="com.demo.App"
4. 核心概念
-
静态代理
-
ImageProxy: 虚拟代理,延迟加载真实图片对象
-
DocumentProxy: 保护代理,根据用户角色控制访问权限
-
-
动态代理
-
LoggingInvocationHandler: 为方法调用添加日志记录
-
CacheInvocationHandler: 为方法添加缓存功能
-
可以灵活组合多个代理处理器
-
-
代理模式优点
-
职责清晰,真实角色只需关注业务逻辑
-
高扩展性,可以方便地添加新功能
-
智能化,动态代理可以灵活处理各种场景
-