Spring(六):代理模式

15 篇文章 0 订阅
1 篇文章 0 订阅

为什么要学习代理模式,因为AOP的底层机制就是动态代理!

代理模式:

  • 静态代理
  • 动态代理

学习AOP之前 , 我们要先了解一下代理模式!

静态代理

静态代理角色分析
  • 抽象角色 : 一般使用接口或者抽象类来实现
  • 真实角色 : 被代理的角色
  • 代理角色 : 代理真实角色 ; 代理真实角色后 , 一般会做一些附属的操作 .
  • 客户 : 使用代理角色来进行一些操作
代码:

1.抽象角色 (租房子)

package com.Devin.demo01;
/*
租房
 */
public interface Rent {
    public void rent();
}

2.真是对象(房东)

package com.Devin.demo01;
/*
房东
 */
public class Host implements Rent{
    public void rent(){
        System.out.println("房东要出租房子!");
    }

}

3.代理角色(中介,可以加一些自己的附属操作)

package com.Devin.demo01;
/*
中介:代理房东的房子,帮房东向外租房子
 */
public class Proxy implements Rent{
    private Host host;

    public Proxy() {
    }

    public Proxy(Host host) {
        this.host = host;
    }

    @Override
    public void rent() {
        host.rent();
    }
    //看房
    public void  sesHouse(){
        System.out.println("中介带你看房");
    }
    //收中介费
    public void  fare(){
        System.out.println("中介收中介费");
    }
    //签合同
    public void  hetong(){
        System.out.println("中介跟你签合同");
    }
}

4.客户(租房的人)

package com.Devin.demo01;
/*
要租房子的人
 */
public class Client {
    public static void main(String[] args) {
        Host host = new Host();
        //new一个代理,现在租房子找代理(中介)
        Proxy proxy = new Proxy(host);
        //租房
        proxy.rent();
        //看房
        proxy.sesHouse();
        //收中介费
        proxy.fare();
        //签合同
        proxy.hetong();
    }

}

分析: 在这个过程中,你直接接触的就是中介,就如同现实生活中的样子,你看不到房东,但是你依旧租到了房东的房子通过代理,这就是所谓的代理模式

静态代理的好处:
  • 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .
  • 公共的业务由代理来完成 . 实现了业务的分工 ,
  • 公共业务发生扩展时变得更加集中和方便 .

缺点 :

  • 类多了 , 多了代理类 , 工作量变大了 . 开发效率降低 .

动态代理

  • 动态代理的角色和静态代理的一样 .

  • 动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的

  • 动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理

    • 基于接口的动态代理----JDK动态代理
    • 基于类的动态代理–cglib
    • 现在用的比较多的是 javasist 来生成动态代理

动态代理需要了解两个类

核心 :

  • InvocationHandler:调用处理程序
  • Proxy:代理
【InvocationHandler:调用处理程序】在这里插入图片描述

在这里插入图片描述

Object invoke(Object proxy,
              Method method,
              Object[] args)
              throws Throwable
    在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。 

参数:
proxy - 在其上调用方法的代理实例
method - 对应于在代理实例上调用的接口方法的 Method 实例。Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。
args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。基本类型的参数被包装在适当基本包装器类(如 java.lang.Integer 或 java.lang.Boolean)的实例中。 

【Proxy : 代理】
public class Proxy
    extends Object
    implements SerializableProxy 
    提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。

    
    动态代理类(以下简称为代理类)是一个实现在创建类时在运行时指定的接口列表的类,该类具有下面描述的行为。 代理接口 是代理类实现的一个接口。 代理实例 是代理类的一个实例。 每个代理实例都有一个关联的调用处理程序 对象,它可以实现接口 InvocationHandler。通过其中一个代理接口的代理实例上的方法调用将被指派到实例的调用处理程序的 Invoke 方法,并传递代理实例、识别调用方法的 java.lang.reflect.Method 对象以及包含参数的 Object 类型的数组。调用处理程序以适当的方式处理编码的方法调用,并且它返回的结果将作为代理实例上方法调用的结果返回。 

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//生成代理类
public Object getProxy(){
   return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                                 rent.getClass().getInterfaces(),this);
}

代码演示

1.真是角色

package com.Devin.demo03;
/*
真是角色:房东
 */
public class Host implements Rent {
    public void rent(){
        System.out.println("房东要出租房子!");
    }

}

2.抽象角色

package com.Devin.demo03;
/*
抽象角色:租房
 */
public interface Rent {
    public void rent();
}

3.程序处理角色

package com.Devin.demo03;

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

/*
自动生成代理类,程序处理角色
 */
public class ProxyInvocationHandler implements InvocationHandler {

    //被代理的接口
    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }

    //生成得到代理类
    public Object getProxy(){
        /*
        Proxy.newProxyInstance(获得ClassLoader, 获得被代理的接口,被代理的InvocationHandler);
         */
        return Proxy.newProxyInstance( this.getClass().getClassLoader(),
                rent.getClass().getInterfaces(),this);
    }


    //处理代理实类,并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //动态代理的本质就是使用反射机只实现!
        //跟静态代理不太一样,静态代理只有写方法,等着调用就可以,动态代理需把方法传进来,调用一个方法会一起执行
        seeHome();
        fare();

        Object result = method.invoke(rent, args);
        return result;
    }

    public void seeHome(){
        System.out.println("中介带你看房子");
    }
    public void fare(){
        System.out.println("中介收中介费");
    }

}

4.测试

package com.Devin.demo03;

public class Client {
    public static void main(String[] args) {
        //真是角色
        Host host = new Host();
        //代理角色  现在没有,只有一个  程序处理角色(动态代理)
        ProxyInvocationHandler handler = new ProxyInvocationHandler();

        //通过调用程序处理角色来处理我们需要调用的接口对象,设置一个真实的代理角色
        handler.setRent(host);

        //得到代理类
        //这里的proxy是动态生成的,我们没有写
        Host proxy = (Host) handler.getProxy();


        proxy.rent();
    }
}

一个动态代理 , 一般代理某一类业务 , 一个动态代理可以代理多个类,代理的是接口!

本文章来源于B站(狂神说) B站地址:https://space.bilibili.com/95256449

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值