GOF23之代理模式

Tina ·
更新时间:2024-11-13
· 816 次阅读

一、核心作用

间接对目标对象进行访问
可以详细控制某个对象的方法,对目标对象的实现功能上,增加额外的功能补充,扩展目标对象功能

二、常见应用场景

1、安全代理:屏蔽对真实角色的直接访问
2、远程代理:通过代理类处理远程方法的调用
3、延时加载:先加载轻量级,真正需要再加载真实对象

三、代理角色分类 抽象角色:定义代理角色和真实角色的公共对外方法 真实角色:实现抽象角色,定义真实角色要实现的业务逻辑,供代理角色调用 代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑来实现抽象方法,并附加自己的操作
在这里插入图片描述 四、代理模式分类:

1、静态代理
2、动态代理
3、Cglib代理

五、代码示例: 一、静态代理: 抽象角色: package com.hezeu.proxy.staticProxy; /** * @Classname Star * @Description 抽象角色 * @Date 2020/2/22 下午 06:41 * @Created by 朱进博 1724282894@qq.com */ public interface Star { void confer(); void signContract(); void bookTicket(); void sing(); void collectMoney(); } 真实角色: package com.hezeu.proxy.staticProxy; /** * @Classname RealStar * @Description TODO * @Date 2020/2/22 下午 06:46 * @Created by 朱进博 1724282894@qq.com */ public class RealStar implements Star { @Override public void confer() { System.out.println("RealStar.confer"); } @Override public void signContract() { System.out.println("RealStar.signContract"); } @Override public void bookTicket() { System.out.println("RealStar.bookTicket"); } @Override public void sing() { System.out.println("RealSta(周杰伦本人).sing"); } @Override public void collectMoney() { System.out.println("RealStar.collectMoney"); } } 代理角色: package com.hezeu.proxy.staticProxy; /** * @Classname ProxyStar * @Description TODO * @Date 2020/2/22 下午 06:48 * @Created by 朱进博 1724282894@qq.com */ public class ProxyStar implements Star{ private Star star; public ProxyStar(Star star) { this.star = star; } @Override public void confer() { System.out.println("ProxyStar.confer"); } @Override public void signContract() { System.out.println("ProxyStar.signContract"); } @Override public void bookTicket() { System.out.println("ProxyStar.bookTicket"); } @Override public void sing() { star.sing(); } @Override public void collectMoney() { System.out.println("ProxyStar.collectMoney"); } } 测试: package com.hezeu.proxy.staticProxy; /** * @Classname Client * @Description 测试 * @Date 2020/2/22 下午 07:58 * @Created by 朱进博 1724282894@qq.com */ public class Client { public static void main(String[] args) { Star real = new RealStar(); Star proxy = new ProxyStar(real); proxy.confer(); proxy.signContract(); proxy.bookTicket(); proxy.sing(); proxy.collectMoney(); } }

测试结果如下:

在这里插入图片描述

静态代理的优缺点:

优点:可以做到不修改目标对象功能的前提下对功能进行扩展或修改,符合开闭原则
缺点:因为代理对象需要与目标对象实现相同的接口,代理类爱多,同时一旦抽象角色增加方法,真实角色和代理角色都要维护,工作量大,不宜管理

二、动态代理: 使用JDK自带的动态代理 java.lang.reflect.Proxy 动态生成代理类和对象 java.lang.reflect.InvocationHandler(处理器接口) 可以通过invoke方法实现对真实角色的代理访问 每次通过proxy生成的代理类对象都要指定对应的处理器对象 package com.hezeu.proxy.dynamicProxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * @Classname StarHandler * @Description TODO * @Date 2020/2/22 下午 08:16 * @Created by 朱进博 1724282894@qq.com */ public class StarHandler implements InvocationHandler { Star realStar; public StarHandler(Star realStar) { this.realStar = realStar; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object obj = null; System.out.println("真正的方法执行前!"); System.out.println("面谈,签合同,预付款,订机票"); if(method.getName().equals("sing")){ obj = method.invoke(realStar, args); } System.out.println("真正的方法执行后!"); System.out.println("收尾款"); return obj; } 动态代理相较于静态代理的优缺点: 对于静态代理而言,动态代理建好了开发的任务,减少了对业务接口的依赖,降低了耦合度 三、Cglib代理:

第三方代理技术,可以对目标对象接口实现代理,也可以进行继承代理,底层是动态的在内存中生成了目标对象的子类的字节码,并生成了相应的对象。
CGlib实现动态代理能满足没有接口的目标对象的代理对象实现。JDK动态代理与CGlib动态代理是实现Spring AOP的基础

代码示例: 真实角色(没有实现接口) package com.hezeu.proxy.CGlib; /** * @Classname RealStar * @Description TODO * @Date 2020/2/22 下午 06:46 * @Created by 朱进博 1724282894@qq.com */ public class RealStar { public void confer() { System.out.println("RealStar.confer"); } public void signContract() { System.out.println("RealStar.signContract"); } public void bookTicket() { System.out.println("RealStar.bookTicket"); } public void collectMoney() { System.out.println("RealStar.collectMoney"); } public void sing() { System.out.println("RealStar(CGlib周杰伦).sing"); } } cglib代理类,需要实现MethodInterceptor package com.hezeu.proxy.CGlib; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * @Classname ProxyStar * @Description TODO * @Date 2020/2/22 下午 10:09 * @Created by 朱进博 1724282894@qq.com */ public class ProxyStar implements MethodInterceptor { private Object target; public Object getInstance(Object target){ this.target=target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass()); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("事物开始"); Object result = methodProxy.invokeSuper(o,objects); System.out.println("事物结束"); return result; } } 测试类: package com.hezeu.proxy.CGlib; /** * @Classname Client * @Description TODO * @Date 2020/2/22 下午 08:20 * @Created by 朱进博 1724282894@qq.com */ public class Client { public static void main(String[] args) { ProxyStar proxy = new ProxyStar(); RealStar realStar = (RealStar) proxy.getInstance(new RealStar()); realStar.sing(); } } 动态代理和CGlib代理总结

使用JDK动态代理需要实现一个或多个接口,若想代理没有实现接口的类,需要使用Cglib
使用Cglib 需要导入
cglib-xxx.jar
asm-xxx.jar

在Spring的AOP编程中
如果加入容器的目标对象有实现接口用JDK代理
如果目标对象没有实现接口,用Cglib代理

感谢阅读,水平有限,如有错漏,还请不吝赐教


作者:Tips。



代理 代理模式

需要 登录 后方可回复, 如果你还没有账号请 注册新账号