Java中静态代理和动态代理设计模式应用实例举例?

静态代理实例

假设我们有一个需求,要记录一个服务接口IService的所有方法调用的开始和结束时间,以此来监控服务的性能。我们可以使用静态代理模式来实现这个需求。

1. 定义服务接口 IService.java:

复制代码

Java

1public interface IService {
2    void serve();
3}

2. 实现服务接口的类 RealService.java:

复制代码

Java

1public class RealService implements IService {
2    @Override
3    public void serve() {
4        System.out.println("真实服务:正在处理请求...");
5    }
6}

3. 创建静态代理类 StaticProxy.java:

复制代码

Java

1public class StaticProxy implements IService {
2    private final IService realService;
3
4    public StaticProxy(IService realService) {
5        this.realService = realService;
6    }
7
8    @Override
9    public void serve() {
10        before();
11        realService.serve();
12        after();
13    }
14
15    private void before() {
16        System.out.println("代理开始:记录调用前时间");
17    }
18
19    private void after() {
20        System.out.println("代理结束:记录调用后时间");
21    }
22}

4. 客户端代码:

复制代码

Java

1public class Client {
2    public static void main(String[] args) {
3        IService service = new RealService();
4        IService proxyService = new StaticProxy(service);
5        proxyService.serve();
6    }
7}

在这个例子中,StaticProxy作为RealService的静态代理,提供了额外的日志记录功能,而无需修改RealService的代码。

动态代理实例

使用JDK动态代理来实现上述相同的需求,动态代理不需要我们手动创建代理类,而是通过反射机制在运行时动态生成。

1. 保持上面的 IServiceRealService 不变。

2. 动态代理实现 DynamicProxy.java:

复制代码

Java

1import java.lang.reflect.InvocationHandler;
2import java.lang.reflect.Method;
3import java.lang.reflect.Proxy;
4
5public class DynamicProxy implements InvocationHandler {
6    private final Object target;
7
8    public DynamicProxy(Object target) {
9        this.target = target;
10    }
11
12    public Object getProxyInstance() {
13        return Proxy.newProxyInstance(
14                target.getClass().getClassLoader(),
15                target.getClass().getInterfaces(),
16                this);
17    }
18
19    @Override
20    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
21        before();
22        Object result = method.invoke(target, args);
23        after();
24        return result;
25    }
26
27    private void before() {
28        System.out.println("动态代理开始:记录调用前时间");
29    }
30
31    private void after() {
32        System.out.println("动态代理结束:记录调用后时间");
33    }
34}

3. 客户端代码调整为使用动态代理:

复制代码

Java

1public class Client {
2    public static void main(String[] args) {
3        IService realService = new RealService();
4        IService proxyService = (IService) new DynamicProxy(realService).getProxyInstance();
5        proxyService.serve();
6    }
7}

在这个动态代理的例子中,我们通过InvocationHandler接口的invoke方法来实现在调用前后增加额外功能,而代理类是由Java运行时动态生成的。这种方式更加灵活,特别是当需要为多个实现同一接口的类创建代理时,避免了为每一个类都手动编写静态代理类的繁琐工作。

相关推荐
鲤籽鲲3 分钟前
C# Random 随机数 全面解析
android·java·c#
zquwei22 分钟前
SpringCloudGateway+Nacos注册与转发Netty+WebSocket
java·网络·分布式·后端·websocket·网络协议·spring
TT哇28 分钟前
*【每日一题 提高题】[蓝桥杯 2022 国 A] 选素数
java·算法·蓝桥杯
火烧屁屁啦1 小时前
【JavaEE进阶】初始Spring Web MVC
java·spring·java-ee
飞飞-躺着更舒服1 小时前
【QT】实现电子飞行显示器(改进版)
开发语言·qt
w_31234541 小时前
自定义一个maven骨架 | 最佳实践
java·maven·intellij-idea
岁岁岁平安1 小时前
spring学习(spring-DI(字符串或对象引用注入、集合注入)(XML配置))
java·学习·spring·依赖注入·集合注入·基本数据类型注入·引用数据类型注入
武昌库里写JAVA1 小时前
Java成长之路(一)--SpringBoot基础学习--SpringBoot代码测试
java·开发语言·spring boot·学习·课程设计
Q_19284999061 小时前
基于Spring Boot的九州美食城商户一体化系统
java·spring boot·后端
张国荣家的弟弟2 小时前
【Yonghong 企业日常问题 06】上传的文件不在白名单,修改allow.jar.digest属性添加允许上传的文件SH256值?
java·jar·bi