Java代理设计模式

news/2025/1/11 18:02:03/

Java代理设计模式

定义

Java代理模式(Proxy Pattern)是一种常用的设计模式,它为其他对象提供一种代理以控制对这个对象的访问。简单来说,我们使用代理对象来代替对真实对象的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。

对应角色

  • Subject(抽象主题角色):它声明了真实主题和代理主题的共同接口,这样一来在任何使用真实主题的地方都可以使用代理主题。
  • Proxy(代理主题角色):它包含了对真实主题的引用,从而可以在任何时候操作真实主题对象;在代理主题角色中提供一个与真实主题角色相同的接口,以便在任何时候都可以替代真实主题;代理主题角色还可以控制对真实主题的使用,负责在需要的时候创建和删除真实主题对象,并对真实主题对象的使用加以约束。
  • RealSubject(真实主题角色):它定义了代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作,客户端可以通过代理主题角色间接调用真实主题角色中定义的操作。

优缺点

优点

  • 职责清晰:真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件事务,附带的结果就是编程简洁清晰。
  • 高扩展性:具体主题角色是随时都会发生变化的,只要它实现了接口,甭管它如何变化,都逃不脱如来佛的手掌(接口),那我们的代理类完全就可以在不做任何修改的情况下使用。

缺点

  • 类个数增加:代理模式会造成系统中类的个数增加,比不使用代理模式增加了代理类,系统的复杂度增加。
  • 性能降低:在客户端和目标对象之间,增加了一个代理对象,造成请求处理速度变慢。

应用场景

  • 需要为一个对象在不同的地址空间提供局部代表的时候,可以使用远程代理。
  • 需要按需创建开销很大的对象的时候,可以使用虚拟代理。
  • 需要控制对象访问权限的时候,可以使用保护代理。

实例

// 抽象主题角色
interface Subject {void request();
}// 真实主题角色
class RealSubject implements Subject {public void request() {System.out.println("RealSubject request");}
}// 代理主题角色
class ProxySubject implements Subject {private RealSubject realSubject;public ProxySubject(RealSubject realSubject) {this.realSubject = realSubject;}public void request() {System.out.println("ProxySubject preRequest");realSubject.request();System.out.println("ProxySubject postRequest");}
}// 客户端
public class Client {public static void main(String[] args) {RealSubject realSubject = new RealSubject();ProxySubject proxySubject = new ProxySubject(realSubject);proxySubject.request();}
}

JDK动态代理(Springboot实现)

首先,我们定义一个接口UserService,它有一个方法getUserById用于根据用户ID获取用户信息。

public interface UserService {String getUserById(Integer id);
}

然后,我们创建一个实现了UserService接口的类UserServiceImpl,并在其中实现getUserById方法。

@Service
public class UserServiceImpl implements UserService {@Overridepublic String getUserById(Integer id) {return "User with id: " + id;}
}

接下来,我们创建一个类UserServiceInvocationHandler,它实现了InvocationHandler接口。在这个类中,我们重写了invoke方法,在其中添加了日志记录功能。

public class UserServiceInvocationHandler implements InvocationHandler {private Object target;public UserServiceInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("Before method: " + method.getName());Object result = method.invoke(target, args);System.out.println("After method: " + method.getName());return result;}
}

最后,在我们的主类中,我们使用Proxy.newProxyInstance方法来创建一个代理对象,并使用这个代理对象来调用getUserById方法。

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {@Autowiredprivate UserService userService;public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}@Overridepublic void run(String... args) throws Exception {UserService proxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),userService.getClass().getInterfaces(),new UserServiceInvocationHandler(userService));System.out.println(proxy.getUserById(1));}
}

当我们运行这个程序时,会看到控制台输出以下内容:

Before method: getUserById
After method: getUserById
User with id: 1

Cglib动态代理(SpringBoot实现)

首先,我们定义一个类UserService,它有一个方法getUserById用于根据用户ID获取用户信息。

public class UserService {public String getUserById(Integer id) {return "User with id: " + id;}
}

接下来,我们创建一个类UserServiceInterceptor,它继承了MethodInterceptor接口。在这个类中,我们重写了intercept方法,在其中添加了日志记录功能。

public class UserServiceInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("Before method: " + method.getName());Object result = methodProxy.invokeSuper(o, objects);System.out.println("After method: " + method.getName());return result;}
}

最后,在我们的主类中,我们使用Enhancer类来创建一个代理对象,并使用这个代理对象来调用getUserById方法。

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}@Overridepublic void run(String... args) throws Exception {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(UserService.class);enhancer.setCallback(new UserServiceInterceptor());UserService proxy = (UserService) enhancer.create();System.out.println(proxy.getUserById(1));}
}

当我们运行这个程序时,会看到控制台输出以下内容:


Before method: getUserById
After method: getUserById
User with id: 1

http://www.ppmy.cn/news/907833.html

相关文章

android 铃音制作工具,音乐剪辑铃声制作

音乐剪辑铃声制作APP最新版下载,这是一款类似铃声快剪的软件,这里分享软件的APK安装包,有需要的用户欢迎下载。 软件介绍 音乐剪辑是一款小巧实用、功能强大、操作简单的音频剪裁铃声制作工具,支持Mp3、AAC、AMR、FLAC、M4A等多种…

什么软件可以提取视频中的音频制作成手机铃声

平常在观看视频时,总忍不住的会被里面的某段背景音乐吸引住这时就想用它当自己的手机铃声,于是便会去搜索此歌曲,但是要下载的话就是一整首起码有三分钟左右的时长,但是一般手机铃声只有十五秒钟左右,那么当然是要截取…

left join 和except方法区别和联系

目录 相同点: left join except 不同点 假设有两个表:A客户表 和 B客户表,客户uid是唯一主键 相同点: 查询在A中的客户 但不在B中,也就是图中的阴影部分,left join 和except方法都可以实现 left join …

unity期末作业,小恐龙跳障碍物游戏-跑酷游戏

小恐龙跳障碍物游戏 unity期末作业,小恐龙跳障碍物的unity3D小游戏,有按钮,有生命离值,有分数值,有游戏音效,可以跳跃行走,掉下跑道生命值减少(为零时游戏结束)&#xf…

小恐龙游戏python_补一波之前说好的用DQN自动玩Chrome浏览器的小恐龙游戏呗~

原文链接补一波之前说好的用DQN自动玩Chrome浏览器的小恐龙游戏呗~​mp.weixin.qq.com 效果展示 在cmd窗口运行如下命令即可: 模型训练: python TRexRush.py --resume 模型测试: python TRexRush.py --mode test 效果如下:dqn玩t-rex rushhttps://www.zh…

学完java制作的一个恐龙跑酷小游戏

小恐龙快跑 该项目是书本上的一个例子,然后自己完成了编程实现。下面分享一些创作的难度和相关技术点。 项目是用java的一些基本操作组成,比如线程的概念,实现动画效果, 学会使用AWT绘制游戏画面,Rectangle类实现碰撞检测&#xf…

用Python实现谷歌的小恐龙游戏

谷歌流量器中有个很有名的彩蛋:当你网络出现问题时,就会出现一个“小恐龙游戏”。 (如果想要直接进行游戏,可以在地址栏输入:chrome://dino 或者++扣扣裙609616831免费领取源码自己做出来玩哦) 今天我们就来给大家演示下,用Python来自己做一个仿制的“小恐龙游戏”! …

基于Pygame实现谷歌浏览器的恐龙快跑小游戏(Python)

前段时间就根据python书上写完这个了,但是没有什么时间写博客,因为现在正好在复习python的一些东西,可以写一下博客来复习梳理一下整个游戏的流程。 文章目录 1.效果展示2.实现主窗体3.游戏背景的滚动3.加入恐龙图片和加入键盘监听实现恐龙跳…