动态代理详解

  1. 代理模式
    代理模式是指,为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客类和目标对象之间起到中介的作用。

  2. 代理模式的作用
    A、控制访问
    B、增强功能

  3. 代理模式分类
    静态代理与动态代理

  4. 代理的实现方式
    需求:用户需要购买 u 盘,u 盘厂家不单独接待零散购买,厂家规定一次最少购买 1000个以上,用户可以通过淘宝的代理商,或者微商哪里进行购买。
    淘宝上的商品,微商都是 u 盘工厂的代理商, 他们代理对 u 盘的销售业务。
    用户购买-------代理商(淘宝,微商)----- u 厂家(金士顿,闪迪等不同的厂家)
    设计这个业务需要的类
    a. 商家和厂家都是提供 sell 购买 u 盘的方法。定义购买 u 盘的接口 UsbSell
    b. 金士顿(King)对购买 1 千以上的价格是 85, 3 千以上是 80, 5 千以上是 75。 单个 120
    元。定义 UsbKingFactory 类,实现 UsbSell
    c. 闪迪(San)对购买 1 千以上的价格是 82, 3 千以上是 78, 5 千以上是 72。 单个 120 元。
    定义 UsbSanFactory 类,实现 UsbSell
    d. 定义淘宝的代理商 TaoBao ,实现 UsbSell
    e. 定义微商的代理商 WeiShang, 实现 UsbSell
    f. 定义测试类,测试通过淘宝, 微商购买 u 盘

     4.1 静态代理
    

    (1) 定义业务接口

    定义业务接口 UsbSell(目标接口),其中含有抽象方法 sell(int amount), sell 是目标方
    法。在这里插入图片描述
    (2) 定义接口实现类

目标类 UsbKingFactory(金士顿 u 盘),该类实现了业务接口。

在这里插入图片描述
(3) 代理商接口
public class Agent implements UsbSell {

private UsbKingFactory factory = new UsbKingFactory();

public float sell(int amount) {
	float price = factory.sell(amount);
	// 在单价之上增加25元的利润
	return price + 25;
}

}
(4) 客户端调用者,购买商品类
public class ShopApplication {

public static void main(String[] args) {
	float price = 0.0f;
	// 代理商
	Agent agent = new Agent();
	price = agent.sell(1);
	System.out.println("代理商购买价格:" + price);
}

}
(5) 静态代理缺点
代理类只服务于一种类型的目标类,如果要服务多个类型。势必要为每一种目标类都进行代理,静态代理在程序规模稍大时就无法胜任了,代理类数量过多。

4.2 动态代理

动态代理是指代理类对象在程序运行时由 JVM 根据反射机制动态生成的。动态代理不需要定义代理类的.java 源文件。

动态代理其实就是 jdk 运行期间,动态创建 class 字节码并加载到 JVM。

动态代理的实现方式常用的有两种:使用 JDK 代理代理,与通过 CGLIB 动态代理。

4.2.1 jdk 的动态代理

jdk 动态代理是基于 Java 的反射机制实现的。使用 jdk 中接口和类实现代理对象的动态创建。
Jdk 的动态要求目标对象必须实现接口,这是 java 设计上的要求。
从 jdk1.3 以来,java 语言通过 java.lang.reflect 包提供三个类支持代理模式 Proxy, Method和 InovcationHandler

(1) InvocationHandler 接口
InvocationHandler 接口叫做调用处理器,负责完成调用目标方法,并增强功能。
通 过 代 理 对 象 执 行 目 标 接 口 中 的 方 法 , 会 把 方 法 的 调 用 分 派 给 调 用 处 理 器(InvocationHandler)的实现类,执行实现类中的 invoke()方法,我们需要把功能代理写在 invoke()方法中 。

InvocationHandler 接口中只有一个方法:
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;
}
在 invoke 方法中可以截取对目标方法的调用。在这里进行功能增强。Java 的动态代理是建立在反射机制之上的。
实现了 InvocationHandler 接口的类用于加强目标类的主业务逻辑。这个接口中有一个方法 invoke(),具体加强的代码逻辑就是定义在该方法中的。通过代理对象执行接口中的方法时,会自动调用 invoke()方法。
invoke()方法的介绍如下:

proxy:代表生成的代理对象
method:代表目标方法
args:代表目标方法的参数

JDK动态代理的实现

jdk 动态代理是代理模式的一种实现方式,其只能代理接口。
实现步骤
1、新建一个接口,作为目标接口
2、为接口创建一个实现类,是目标类
3、创建类实现 java.lang.reflect.InvocationHandler 接口,调用目标方法并增加其他功能代码
4、创建动态代理对象,使用 Proxy.newProxyInstance()方法,并把返回值强制转为接口类型。

public class ShopApplication2 {

public static void main(String[] args) {
	// 创建代理
	UsbKingFactory target = new UsbKingFactory();
	// 创建调用处理器
	MySellHandler proxyHandler = new MySellHandler(target);
	// 创建jdk动态代理
	UsbSell usbSell = (UsbSell) Proxy.newProxyInstance(target.getClass().getClassLoader(), 
			target.getClass().getInterfaces(), proxyHandler);
	// 通过代理对象执行业务方法,实现利润增加
	float price = usbSell.sell(1);
	System.out.println("动态代理价格:" + price);
}

}

执行流程:
Client --> 动态代理对象Proxy --> InvocationHandler 调用处理器截取对象方法的调用。

5. cgLib 代理
CGLIB(Code Generation Library)是一个开源项目。是一个强大的,高性能,高质量的 Code 生成类库,它可以在运行期扩展 Java 类与实现 Java 接口。它广泛的被许多 AOP 的框架使用,例如 Spring AOP。
使用 JDK 的 Proxy 实现代理,要求目标类与代理类实现相同的接口。若目标类不存在接口,则无法使用该方式实现。
但对于无接口的类,要为其创建动态代理,就要使用 CGLIB 来实现。CGLIB 代理的生成原理是生成目标类的子类,而子类是增强过的,这个子类对象就是代理对象。所以,使用CGLIB 生成动态代理,要求目标类必须能够被继承,即不能是 final 的类。
cglib 经常被应用在框架中,例如 Spring ,Hibernate 等。Cglib 的代理效率高于 Jdk。对于 cglib 一般的开发中并不使用。做了一个了解就可以

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

guyuweilove

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值