【Spring】静态代理与动态代理

一、什么是代理

我使用一个比较形象的例子,假如说你要租房子,那么有两种方式,第一种方式:可以直接找房主,和房主进行协商;第二种方式:直接找中介,那么这里的中介就相当于是房主的一个代理。
在这里插入图片描述
在代理中一般会涉及以下几个角色

  • 抽象角色:一般会使用抽象类和接口来解决
  • 真是角色:得代理的角色
  • 代理角色:代理真实角色,代理这真实角色后,一般会做一些负数操作
  • 客户角色:访问代理角色的人

二、为什么需要代理

代理的目的是为了使被代理类的功能更加纯粹,不用考虑其他的问题,其他的一些操作都可以在代理类中完成。

在javaweb中就用一个典型的例子,我们可以将service层看做是dao层的代理,dao层需要专注于纯粹的数据库交互。

代理的好处:

  1. 可以使真实角色的操作更加纯粹,不用关注一些公共的业务。
  2. 公共的业务直接交给代理角色,实现了业务的分工。
  3. 公共业务发生扩展时,可以集中操作。

三、静态代理

所谓的静态代理,就是对于一个实体类。我们需要为每一个实体类创建一个代理类。

静态代理对于有一定java基础的人而言,还是很简单的。

实体类(实体类的原代理就不写了)
在这里插入图片描述


代理类Host01Proxy :

public class Host01Proxy {
    private Host01 host;

    public Host01Proxy() {
    }

    public Host01Proxy(Host01 host) {
        this.host = host;
    }

    public void getAddress(){
        host.address();
    }
    public void getprice(){
        host.price();
    }
    public void getarea(){
        host.area();
    }
}

代理类Host02Proxy :

public class Host02Proxy {
    private Host02 host;

    public Host02Proxy() {
    }

    public Host02Proxy(Host02 host) {
        this.host = host;
    }

    public void getAddress(){
        host.address();
    }
    public void getprice(){
        host.price();
    }
    public void getarea(){
        host.area();
    }
}

代理类Host03Proxy :

public class Host03Proxy {
    private Host03 host;

    public Host03Proxy() {
    }

    public Host03Proxy(Host03 host) {
        this.host = host;
    }

    public void getAddress(){
        host.address();
    }
    public void getprice(){
        host.price();
    }
    public void getarea(){
        host.area();
    }
}

测试:

    @Test
    public void test(){
        Host01Proxy host = new Host01Proxy(new Host01());
        host.getAddress();
        host.getarea();
        host.getprice();
        System.out.println("---------------------------------");

        Host02Proxy host1 = new Host02Proxy(new Host02());
        host1.getAddress();
        host1.getarea();
        host1.getprice();
        System.out.println("---------------------------------");

        Host03Proxy host2 = new Host03Proxy(new Host03());
        host2.getAddress();
        host2.getarea();
        host2.getprice();
        System.out.println("---------------------------------");


    }

在这里插入图片描述

四、动态代理

本质上是通过反射实现的,反射是万能的。

动态代理的分类:

  • 基于接口的动态代理
    • JDK动态代理(我们在这里使用此种方式)
  • 基于类的动态代理
    • cglib
  • java字节码实现
    • JAVAssist

在实现动态代理之前,需要了解的两个类:

Proxy :代理类

Proxy提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。

我可以通过.newProxyInstance为某个接口创建代理,关于这个方式的详细说明,如下图:
在这里插入图片描述


InvocationHandler :调用处理程序

InvocationHandler是由代理实例的调用处理程序实现的接口.

每个代理实例都有一个关联的调用处理程序。 当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的invoke方法。

该接口中之后一个抽象方法invoke,具体介绍如下:
在这里插入图片描述


实体类(实体类的原代理就不写了)
在这里插入图片描述

代理类(基本就是固定写法):

public class ProxyInvocationHandler implements InvocationHandler {
    public Rent rent;

    //设置实现了rent接口的被代理类
    public void setRent(Rent rent) {
        this.rent = rent;
    }

    //获取代理类
    public Object getProxy(){
        return Proxy.newProxyInstance(
                this.getClass().getClassLoader(), //类加载器
                rent.getClass().getInterfaces(), //被代理类的公共接口
                this);//因为本类实现了InvocationHandler,所以就是this
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("我是代理类,下面是你想要的信息:");

        //通过Method调用invoke
        Object invoke = method.invoke(rent, args);
        return invoke;
    }
}

测试:

public class MyTest {
    @Test
    public void test(){
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        pih.setRent(new Host01());
        Rent proxy = (Rent)pih.getProxy();
        proxy.address();
        proxy.area();
        proxy.price();
        System.out.println("----------------------------------");

        pih.setRent(new Host02());
        Rent proxy2 = (Rent) pih.getProxy();
        proxy2.address();
        proxy2.area();
        proxy2.price();
        System.out.println("----------------------------------");

        pih.setRent(new Host03());
        Rent proxy3 = (Rent) pih.getProxy();
        proxy3.address();
        proxy3.area();
        proxy3.price();
        System.out.println("----------------------------------");
    }
}

在这里插入图片描述


动态代理的好处:

  1. 可以使真实角色的操作更加纯粹,不用关注一些公共的业务
  2. 公共的业务直接交给代理角色,实现了业务的分工
  3. 公共业务发生扩展时,可以集中操作
  4. 一个动态代理类代理的是一个接口,一般就是对应的一类业务
  5. 一个动态代理类可以代理多个类,只要是实现了同一个接口即可
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值