玩转JAVA代理模式

Posted 我想月薪过万

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了玩转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 就会非常简单,因为它都不用管你的接口,直接覆写类的所有方法,大家可以百度自行尝试。

文章链接:代理模式之 cglib

以上是关于玩转JAVA代理模式的主要内容,如果未能解决你的问题,请参考以下文章

代理模式之 cglib

一文彻底教会你玩转java动态代理

一文彻底教会你玩转java动态代理

一文彻底教会你玩转java动态代理

Java RMI地址解析问题

java代码实现设计模式之代理模式