06设计模式-代理模式
Posted wfdespace
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了06设计模式-代理模式相关的知识,希望对你有一定的参考价值。
1.5.深入分析代理模式
1.5.1.深度分析代理模式【上】
时长:46min
学习目标:
》代理模式的应用场景及实现原理
》区分静态代理与动态代理
》cglib和jdk Proxy实现动态代理的区别
》手写实现定义的动态代理
》spring Aop基于动态代理,打下基础
5.1.代理模式定义
5.1.1.什么是代理模式?
Proxy Pattern,是指为其他对象提供一种代理,以控制对这个对象的访问。
代理对象,在客户端与目标对象之间起到中介作用,起到功能增强的作用。
属于结构型设计模式。
代理之生活理解:
可以参照中介来理解。如:租房中介,用户需要租房子,但是找不到或没时间找房子【用户功能不够强大】,那么,
就找到一个代理【中介】,中介是专门找到房子的【他的功能比用户强大】,最后中介帮用户找到了房子。
所以,代理是对目标对象【用户】功能的增强。
生活中代理场景:
房产中介,快递小哥,黄牛党。
5.1.2.代理模式的适用场景
》保护目标对象
》增强目标对象
5.2.代理模式的实现示例代码
5.2.1.通用写法
5.2.1.1.目标对象定义
由于面向接口编程,定义顶层接口:
package com.wf.proxy.general; /** * @ClassName ISubject * @Description 目标对象的抽象接口 * @Author wf * @Date 2020/5/15 17:00 * @Version 1.0 */ public interface ISubject { void request(); }
目标对象实现:
package com.wf.proxy.general; /** * @ClassName RealSubject * @Description 目标对象 * @Author wf * @Date 2020/5/15 17:02 * @Version 1.0 */ public class RealSubject implements ISubject { @Override public void request() { System.out.println("目标对象真实的服务实现"); } }
5.2.1.2.代理类定义
package com.wf.proxy.general; /** * @ClassName Proxy * @Description 代理对象 * @Author wf * @Date 2020/5/15 17:05 * @Version 1.0 */ public class Proxy implements ISubject { //代理对象 需要对目标对象的功能进行增强 //即增强目标对象的方法,所以实现同一接口 //增强目标对象,所以个课程目标对象【基于多态,可以引入顶层接口bean】 private ISubject subject; //客户端要传参目标对象,这里定义构建器传参 public Proxy(ISubject subject) { this.subject = subject; } //程序中,什么叫功能增强,就是多加一段代码,提供更多功能 @Override public void request() { doBefore(); //方法前增强 subject.request(); //方法后增强 doAfter(); } private void doAfter() { System.out.println("方法后面进行增强"); } private void doBefore() { System.out.println("方法前面进行增强"); } }
5.2.1.3.客户端调用
package com.wf.proxy.general; /** * @ClassName Client * @Description 客户端调用 * @Author wf * @Date 2020/5/15 17:15 * @Version 1.0 */ public class Client { public static void main(String[] args) { RealSubject subject = new RealSubject(); Proxy proxy = new Proxy(subject); proxy.request(); } }
测试结果如下:
说明:
显然,request方法的功能得到了增强。
5.2.1.4.系统类图
5.3.静态代理与动态代理
5.3.1.什么是静态代理?
先以一个生活场景,通过代码来说明。
程序员平时加班较多,没时间找对象-----------父母着急,帮忙物色对象【充当代理】,安排相亲-------最后找到女朋友。
抽象出业务模型
Person----Parent-----------findLove
5.3.1.1.代码示例
1.定义顶层接口
package com.wf.proxy.staticproxy; /** * @ClassName IPerson * @Description 程序员顶层抽象接口 * @Author wf * @Date 2020/5/15 17:31 * @Version 1.0 */ public interface IPerson { void findLove(); }
2.目标对象
package com.wf.proxy.staticproxy; /** * @ClassName Person * @Description 程序员 目标对象 * @Author wf * @Date 2020/5/15 17:33 * @Version 1.0 */ public class Person implements IPerson { @Override public void findLove() { System.out.println("程序员,自己没有找到女朋友"); } }
3.代理类---父母
package com.wf.proxy.staticproxy; /** * @ClassName ParentProxy * @Description 父母 代理类 * @Author wf * @Date 2020/5/15 17:36 * @Version 1.0 */ public class ParentProxy implements IPerson { private IPerson person; public ParentProxy(IPerson person) { this.person = person; } @Override public void findLove() { // System.out.println("开始帮儿子,物色对象"); person.findLove(); System.out.println("儿子说,ok,开始交往"); } }
4.客户端代码
package com.wf.proxy.staticproxy; /** * @ClassName Client * @Description 客户端调用类 * @Author wf * @Date 2020/5/15 17:41 * @Version 1.0 */ public class Client { public static void main(String[] args) { Person person = new Person(); ParentProxy proxy = new ParentProxy(person); proxy.findLove(); } }
测试结果如下:
说明:
因为有大量人可能也没有找到对象,针对这种需求,社会上形成一个产业链,叫婚介所,婚恋网。
因此,系统需要扩展。
但是,张三的父母,力量有限,只能给儿子一个人物色对象。
如果李四也想找到张三的父母物色对象,就没办法完成。也就是父母这个代理只能代理儿子的事情。
这就是静态代理。
如果想要为更多人做代理,代理需要更为强大,于是,产生动态代理。
静态代理:
只能代理某特定的目标对象。如:房产中介,只能代理租客。
动态代理:
代理对象可以代理任意的目标对象。
5.3.2.动态代理的实现
在java中,动态代理有两种实现方案:
》jdk Proxy代理类实现
》cglib库实现
5.3.2.1.jdk实现动态代理
1.婚介所代理类创建
package com.wf.proxy.dynamicproxy.jdkproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * @ClassName MarriageAgency * @Description 婚介所 代理类 * @Author wf * @Date 2020/5/15 18:23 * @Version 1.0 */ public class MarriageAgency implements InvocationHandler { //jdk动态代理 实现一个抽象的接口【接口可以定义任意功能】 //加强目标对象功能,需要引入目标对象 private IPerson person; public IPerson getProxy(IPerson person) { this.person = person; //根据目标对象,得到代理对象 //jdk底层是基于字节码,需要传参代理类的类加载器,并且代理对象需要实现接口功能【传参接口,实例this】 Class<? extends IPerson> personClass = person.getClass(); return (IPerson)Proxy.newProxyInstance(personClass.getClassLoader(), personClass.getInterfaces(),this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //加强目标对象的方法 doBefore(); Object result = method.invoke(this.person, args); doAfter(); return result; } private void doAfter() { System.out.println("是不是确认关系,开始交往"); } private void doBefore() { System.out.println("开始物色对象"); } }
2.顶层接口类
package com.wf.proxy.dynamicproxy.jdkproxy; /** * @ClassName IPerson * @Description 程序员顶层抽象接口 * @Author wf * @Date 2020/5/15 17:31 * @Version 1.0 */ public interface IPerson { void findLove(); }
以上是关于06设计模式-代理模式的主要内容,如果未能解决你的问题,请参考以下文章