玩转JAVA代理模式java 代理模式
代理模式 是指为其他对象提供一种代理,以控制对这个对象的访问,代理对象在 客户端和目标对象 之间起到中介作用,属于结构型设计模式。
应用场景该 设计模式 灵活的运用在 spring 的AOP(面向切片编程)中。
模式分类静态代理、动态代理
实例演示静态代理
场景描述:《相亲》张三有个找媳妇的需求,于是他找到了媒婆,媒婆就去物色美女满足张三的需求。
从上面这个场景中,我们可以看到:媒婆和张三 有一个共性都是人并且都有找美女的需求。所以,我们创建一个人的接口,一个张三类和一个媒婆类。
IPerson 接口
package proxy; /** * ClassName: IPerson <br/> * Description: <br/> * date: 2021/7/9 17:37<br/> * * @author yiqi<br /> * @since JDK 1.8 */ public interface IPerson { void findBeauty(); }张三 类
package proxy; /** * ClassName: ZhangSan <br/> * Description: <br/> * date: 2021/7/9 17:40<br/> * * @author yiqi<br /> * @since JDK 1.8 */ public class ZhangSan implements IPerson{ @Override public void findBeauty() { System.out.println("相亲要求:皮肤白,大长腿"); } }媒婆 类
package proxy; /** * ClassName: MeiPo <br/> * Description: <br/> * date: 2021/7/9 17:42<br/> * * @author yiqi<br /> * @since JDK 1.8 */ public class MeiPo implements IPerson{ private ZhangSan zhangSan; public MeiPo(ZhangSan zhangSan) { this.zhangSan = zhangSan; } @Override public void findBeauty() { System.out.println("走遍世界,寻找美女"); zhangSan.findBeauty(); System.out.println("如期交货"); } }测试代码
package proxy; /** * ClassName: Main <br/> * Description: <br/> * date: 2021/7/9 21:21<br/> * * @author yiqi<br /> * @since JDK 1.8 */ public class Main { public static void main(String[] args) { MeiPo meiPo = new MeiPo(new ZhangSan()); meiPo.findBeauty(); } }运行效果
善于思考的同学会发现这个存在一个弊端,那就是 这个媒婆代理存在局限性,只能为张三服务,这样肯定是不行滴,所以,出现了下面的动态代理。
动态代理
动态代理,就是动态创建代码在JVM虚拟机内存中跑,这个类是动态创建的,只存在于JVM内存中,不存在于实际。
实现方式:jdk库或cglib库
代码示例
人类 接口
package jdkProxy; /** * ClassName: IPenson <br/> * Description: <br/> * date: 2021/7/10 10:04<br/> * * @author yiqi<br /> * @since JDK 1.8 */ public interface IPenson { void findBeauty(); }媒婆代理 类
package jdkProxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * ClassName: JDKMeiPo <br/> * Description: <br/> * date: 2021/7/10 10:12<br/> * * @author yiqi<br /> * @since JDK 1.8 */ public class JDKMeiPo implements InvocationHandler { //第二步:存储需要代理的对象,方便第三步使用 private Object mTarget; //第一步:获取动态创建的实例对象 public Object getInstance(Object target){ mTarget = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //第三步:执行被调用的方法 before(); method.invoke(mTarget,args); after(); return null; } private void after() { System.out.println("如期交货"); } private void before() { System.out.println("走遍世界,寻找美女"); } }张三 类
package jdkProxy; /** * ClassName: ZhangSan <br/> * Description: <br/> * date: 2021/7/10 10:20<br/> * * @author yiqi<br /> * @since JDK 1.8 */ public class ZhangSan implements IPenson{ @Override public void findBeauty() { System.out.println("相亲要求:皮肤白,大长腿"); } }测试类
package jdkProxy; /** * ClassName: test <br/> * Description: <br/> * date: 2021/7/10 10:19<br/> * * @author yiqi<br /> * @since JDK 1.8 */ public class test { public static void main(String[] args) { //第一步:创建代理 JDKMeiPo jdkMeiPo = new JDKMeiPo(); //第二步:获取动态创建的实体类 ,注意 这个实体类是动态创建的,已经不是张三了 IPenson penson = (IPenson) jdkMeiPo.getInstance(new ZhangSan()); //第三步:这个方法不是直接调用张三的 findBeauty() 方法,而是触发 invoke() 的调用 penson.findBeauty(); } }效果展示
如果大家领悟了上面动态代理的真谛,那么学习 cglib 就会非常简单,因为它都不用管你的接口,直接覆写类的所有方法,大家可以百度自行尝试。