Java 基础(接口的应用:结构型设计模式-代理模式 Proxy)
-
概述:
代理模式是Java开发中使用较多的一种设计模式。代理设计就是为其他对象提供一种代理以控制对这个对象的访问。 -
应用场景:
安全代理: 屏蔽对真实角色的直接访问。I
远程代理: 通过代理类处理远程方法调用(RMI)
延迟加载: 先加载轻量级的代理对象,真正需要再加载真实对象。比如你要开发一个大文档查看软件,大文档中有大的图片,有可能一个图片有100MB,在打开文件时,不可能将所有的图片都显示出来,这样就可以使用代理模式,当需要查看图片时,用proxy来进行大图片的打开。
- 分类:
静态代理(静态定义代理类)
动态代理 (动态生成代理类)
JDK自带的动态代理,需要反射等知识
NetWorkTest.java
package com.klvchen.java1; public class NetWorkTest { public static void main(String[] args) { Server server = new Server(); ProxyServer proxyServer = new ProxyServer(server); proxyServer.browse(); } } interface NetWork{ public void browse(); } //被代理类 class Server implements NetWork{ @Override public void browse() { System.out.println("真实的服务器访问网络"); } } //代理类 class ProxyServer implements NetWork{ private NetWork work; public ProxyServer(NetWork work) { this.work = work; } public void check() { System.out.println("联网之前的检查工作"); } @Override public void browse() { check(); work.browse(); } }
静态代理
StaticProxyTest.java
package com.klvchen.java1; public class StaticProxyTest { public static void main(String[] args) { Star s = new Proxy(new RealStar()); s.confer(); s.signContract(); s.bookTicket(); s.sing(); s.collectMoney(); } } interface Star{ void confer(); // 面议 void signContract(); // 签合同 void bookTicket(); // 订票 void sing(); // 唱歌 void collectMoney(); // 收钱 } class RealStar implements Star { @Override public void confer() { } @Override public void signContract() { } @Override public void bookTicket() { } @Override public void sing() { System.out.println("明星, 唱歌~~~~"); } @Override public void collectMoney() { } } //代理类 class Proxy implements Star{ private Star real; public Proxy(Star real) { super(); this.real = real; } @Override public void confer() { System.out.println("经纪人面谈"); } @Override public void signContract() { System.out.println("经纪人签合同"); } @Override public void bookTicket() { System.out.println("经纪人订票"); } @Override public void sing() { real.sing(); } @Override public void collectMoney() { System.out.println("经纪人收钱"); } }
动态代理
动态代理是指客户通过代理类来调用其它对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象。
动态代理使用场合:
1.调试
2.远程方法调用
动态代理相比于静态代理的优点:
抽象角色中(接口)声明的所有方法都被转移到调用处理器一个集中的方法中处理,这样,我们可以更加灵活和统一的处理众多的方法。
动态代理与AOP (Aspect Orient Programming)
StaticProxyTest.java
package com.klvchen.java; /* 静态代理举例 特点:代理类和被代理类在编译期间,就确定下来了。 */ interface ClothFactory{ void produceCloth(); } //代理类 class ProxyClothFactory implements ClothFactory { private ClothFactory factory; //用被代理类对象进行实例化 public ProxyClothFactory(ClothFactory factory) { this.factory = factory; } @Override public void produceCloth() { System.out.println("代理工厂做一些准备工作"); factory.produceCloth();; System.out.println("代理工厂做一些后续的收尾工作"); } } //被代理类 class NikeClothFactory implements ClothFactory { @Override public void produceCloth() { System.out.println("Nike工厂生产一批运动服"); } } public class StaticProxyTest { public static void main(String[] args) { //创建被代理类的对象 NikeClothFactory nike = new NikeClothFactory(); //创建代理类的对象 ProxyClothFactory proxyClothFactory = new ProxyClothFactory(nike); proxyClothFactory.produceCloth(); } }
ProxyTest.java
package com.klvchen.java; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; interface Human{ String getBelief(); void eat(String food); } //被代理类 class SuperMan implements Human { @Override public String getBelief() { return "I believe I can fly"; } @Override public void eat(String food) { System.out.println("我喜欢吃" + food); } } class HumanUtil{ public void method1(){ System.out.println("========================== 通用方法一 =========================="); } public void method2(){ System.out.println("========================== 通用方法二 =========================="); } } /* 要想实现动态代理,需要解决的问题? 问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象。 问题二:当通过代理类的对象调用方法时,如何动态的去调用被代理类中的同名方法。 */ class ProxyFactory { // 调用此方法,返回一个代理类的对象。解决问题一 public static Object getProxyInstance(Object obj) { //obj: 被代理类对象 MyInvocationHandler handler = new MyInvocationHandler(); handler.bind(obj); return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler); } } class MyInvocationHandler implements InvocationHandler{ private Object obj;//需要使用被代理类的对象进行赋值 public void bind(Object obj) { this.obj = obj; } //当我们通过代理类的对象,调用方法a时,就会自动的调用如下的方法: invoke() //将被代理类要执行的方法a的功能就声明在invoke()中 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { HumanUtil util = new HumanUtil(); util.method1(); //method:即为代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法 //obj:被代理类的对象 Object returnValue = method.invoke(obj, args); util.method2(); //上述方法的返回值就作为当前类中的invoke()的返回值。 return returnValue; } } public class ProxyTest { public static void main(String[] args) { SuperMan superMan = new SuperMan(); //proxyInstance:代理类的对象 Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan); //当通过代理类对象调用方法时,会自动的调用被代理类中同名的方法 proxyInstance.getBelief(); proxyInstance.eat("四川麻辣烫"); System.out.println("*****************************************"); NikeClothFactory nikeClothFactory = new NikeClothFactory(); ClothFactory proxyClothFactory = (ClothFactory) ProxyFactory.getProxyInstance(nikeClothFactory); proxyClothFactory.produceCloth(); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY