小时候有个梦想就是长大了去西安做销售

写在前面的话:

        时间:2022.1.24

        地点:长安

        人物:冷妆

        事件:本篇文章讨论在搭建集群或分布式架构时:多台服务器之间实现远程通信,具体包括的网络模型(OSI以及TCP/IP网络模型),代理模式(静、动态代理)和远程调用(RPC与RMI对比以及RPC与HTTP对比)

引入正题之实战远程调用的设计模式--代理模式

通过租房的案例来理解静、动态代理模式

租房代理商--静态代理

上图为静态代理实现的脉络图,主要想强调真实角色(房东)与代理角色(中介)的关系是一对一的,它两都是实现了房子(真实角色和代理角色共同维护的方法)这个接口,真实角色(房东)实现了这个接口并重写其方法,代理角色(中介)也是实现了这个接口,但是代理角色执行的其实是真实角色中的方法,代码参考如下

租房这个接口

package com.lengzhuang.proxy;

public interface Subject {
    //定义了租房的抽象方法
    public  abstract  boolean rent(int money);
}

真实角色(房东)

package com.lengzhuang.proxy;

public class RealSubject implements  Subject {
    //房东关心的是-->房子租出去没,收租
    @Override
    public boolean rent(int money) {
        System.out.println("房租"+money+"元");
        return true;
    }
}

代理角色(中介)

package com.lengzhuang.proxy;

public class ProxySubject implements  Subject{
    //代理角色:执行真实角色中的方法+一些其他的操作
    //含有真实对象的引用
    Subject realSubject = new RealSubject();

    public void before()
    {
        System.out.println("before...");
    }
    public  void after()
    {
        System.out.println("after...");
    }
    @Override
    public boolean rent(int money) {
        this.before();
        realSubject.rent(money);
        this.after();
        return true;
    }
}

测试

package com.lengzhuang.proxy;

public class Test {
    public static void main(String[] args) {
        //调用代理角色
       Subject subject =  new ProxySubject();
       subject.rent(2000);
    }
}

运行结果与包结构展示如下

静态代理主要强调就是一一对应的关系,所以销售行业是经久不衰的,毫不夸张的说,销售在公司中占了绝对作用,但是售楼的,卖车的各行各业,总不能去搞360个重复的代码量,所以对于开发来说很不友好,最终的结果呢,中介不吃香了,得找个管家来给我都安排的明明白白

万能代理商--动态代理 

        在动态代理中真实角色和代理角色是“多对一”的关系,一个万能的代理者(管家)来代理任何类型的真实角色,由JDK提供的”万能“动态代理接口--InvocationHandler,该接口中的invoke()方法就是万能的代理方法,代码示例如下

代理角色与真实角色共同维护的方法

package com.lengzhuang.proxy.Dynamic;

public interface Subject {
    //定义了租房的抽象方法
    public  abstract  boolean rent(int money);
}

真实角色类

package com.lengzhuang.proxy.Dynamic;

public class RealSubject implements  Subject {
    //房东关心的是-->房子租出去没,收租
    @Override
    public boolean rent(int money) {
        System.out.println("房租"+money+"元");
        return true;
    }
}

以上代码其实静/动态代理是相同的

代理角色类

package com.lengzhuang.proxy.Dynamic;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class ProxySubject  implements InvocationHandler {
    //可以代理任意角色-->对比于静态代理,这里实现的其实是真实角色的方法
    private  Object object;

    public ProxySubject(Object object) {
        this.object = object;
    }

    public  void before()
    {
        System.out.println("before");
    }
    /**
     *
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     * proxy代理角色
     * method被代理的方法
     * args方法参数
     * return真正被代理方法的返回值
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        this.before();
        Object result = method.invoke(object,args);
        this.after();
        return result;
    }
    public  void after(){
        System.out.println("after");
    }
}

测试类

package com.lengzhuang.proxy.Dynamic;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Test {
    public static void main(String[] args) {
        //实例化真实角色
      Subject realSubject =   new RealSubject();
      //代理角色就是真实角色的代理对象
        InvocationHandler handler = new  ProxySubject(realSubject);
        /**
         * Proxy.newProxyInstance(1,2,3)
         * 1 代理角色的类加载器
         * 2 真实角色的接口类型的数组
         * 3.初始代理对象
         */
        Subject subjectproxy =(Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler);
        boolean result = subjectproxy.rent(2000);
        System.out.println(result?"ok":"error");
    }
}

运行结果

以上通过租房的案例来理解了动态代理

 先通过写自定义接口,然后真实角色实现接口,代理角色实现了InvocationHandler,重写了invoke()方法,然后真实角色传入代理角色,通过Proxy.newProxyInstance()生成真正的代理对象并返回调用实现的方法,租车的案例代码参考如下

自定义接口

package com.lengzhuang.proxy;

public interface Subject2 {
    void rentCar(String type);
}

 真实角色类

package com.lengzhuang.proxy;

public class RealSubject2 implements Subject2 {
    @Override
    public void rentCar(String type) {
        System.out.println("车是"+type);
    }
}

代理角色类

package com.lengzhuang.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class ProxySubject2 implements InvocationHandler {

    private Object object;

    public ProxySubject2(Object object) {
        this.object = object;
    }

    public  void before()
    {
        System.out.println("before");
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        this.before();
        Object result = method.invoke(object, args);
        this.after();
        return result;
    }

    public void after()
    {
        System.out.println("after");
    }
}

测试Code如下

package com.lengzhuang.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Test {
    public static void main(String[] args) {
        Subject2 realSubject2 = new RealSubject2();
        InvocationHandler handler = new ProxySubject2(realSubject2);
        Subject2 subproxy = (Subject2)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject2.getClass().getInterfaces(), handler);
        subproxy.rentCar("保时捷");
    }
}

运行结果


碎碎念:

        下文-->远程调用(RPC与RMI对比以及RPC与HTTP对比)

        欢迎大家指出blog中的问题,督促笔者进一步改善

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值