代理模式

1.何为代理模式

目的:为其他对象提供一种代理以控制这个对象的访问

何时使用:想在访问一个类时做一些控制

解决方案:增加中间层

优点:高扩展性、清晰

缺点:实现代理模式需要额外的工作,可能会造成请求的处理速度变慢

SpringAOP的底层就是代理模式

代理模式的分类

静态代理
动态代理

2.静态代理

举一个生活中租房子的例子

角色分析:

  • 抽象角色:一般会使用接口或抽象类来解决(租房)
  • 真实角色:被代理的角色(房东)
  • 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作(中介)
  • 客户:访问代理对象的人(租房的人)

再来加深一下理解

代理模式的好处

>    可以使真实角色的操作更加纯粹!不用去关注一些公共的业务(房东只想着租房子,不想打广告啦,签合同之类)
>    公共业务发生扩展的时候方便集中管理
>    降低耦合

缺点

>    一个真实角色就会产生一个代理角色;代码量会翻倍~开发效率会变低

为解决这一问题需要用到动态代理~

3. 动态代理

特点:字节码随用随创建,随用随加载

作用:不修改源码的基础上对方法增强

  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是直接写好的
  • 动态代理分为两大类

    基于接口的动态代理(JDK动态代理)
    基于类的动态代理(cglib)

需要了解的两个类:Proxy(代理),InvocationHandler(调用处理程序)

InvocationHandler官方文档

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

返回值 描述
Object invoke(Object proxy,方法 method,Object[] args)处理代理实例上的方法调用并返回结果

如何创建代理对象?

使用Proxy类中的newProxyInstance方法

创建代理的要求:

被代理类最少实现一个接口,如果没有则不能使用

newProxyInstance()方法的三个参数

ClassLoader:类加载器

  • 用于加载代理对象字节码的,和被代理对象使用相同的类加载器。固定写法

    Class[]:字节码数组

  • 用于让代理对象和被代理对象有相同的方法。固定写法

    InvocationHandler:用于提供增强的代码

  • 让我们写如何代理,一般都是该接口的实现类,谁用写谁

使用动态代理来实现租房案例

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package xyz.demo2;

public class Client {
public static <R> void main(String[] args) {
//真实角色
Host host = new Host();
//代理角色
ProxyInvocationHandler pih = new ProxyInvocationHandler();
//通过调用程序处理角色来处理我们要调用的接口对象
pih.setRent(host);
rent proxy = (rent) pih.getProxy();
proxy.rent();

//房东要出租房子
}
}

分析

getProxy方法返回代理对象,这个代理对象是代理类的一个实例,代理类也实现了Rent接口重写了rent方法,所以代理对象proxy调用rent方法就会在代理类的rent方法中调用invoke方法

加深理解

总结

动态代理主要是通过反射机制,在运行时动态生成所需代理的class。我们可以直接去使用动态代理类,但必须要了解的是Proxy和InvocationHandler,Proxy是生成动态代理实例的,InvocationHandler是调用程序并返回结果的

请我喝杯咖啡吧~

支付宝
微信