JDK动态代理入门

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

换句话说,使用代理对象,是为了在不修改目标对象的基础上,增强主业务逻辑。客户类真正的想要访问的对象是目标对象,但客户类真正可以访问的对象是代理对象。客户类对目标对象的访问是通过访问代理对象来实现的。当然,代理类与目标类要实现同一个接口。
例如: 有 A,B,C 三个类, A 原来可以调用 C 类的方法, 现在因为某种原因 C 类不允许,A 类调用其方法,但 B 类可以调用 C 类的方法。A 类通过 B 类调用 C 类的方法。这里 B 是 C的代理。 A 通过代理 B 访问 C.

2、代理模式的作用
1、控制访问
2、功能增强
3、代理模式的分类
1、静态代理
2、动态代理
4静态代理

4.1、静态代理:
    1)代理类是自己手工实现的,自己创建一个java类,表示代理类。
    2)同时你所要代理的目标类是确定的。
4.2、静态代理的代码实现
   1)需求:
        需求:用户需要购买 u 盘,u 盘厂家不单独接待零散购买,厂家规定一次最少购买 1000个以上,用户可以通过淘宝的代理商,或者微商哪里进行购买。淘宝上的商品,微商都是 u 盘工厂的代理商, 他们代理对 u 盘的销售业务。用户购买-------代理商(淘宝,微商)----- u 厂家(金士顿,闪迪等不同的厂家)设计这个业务需要的类:
        1. 商家和厂家都是提供 sell 购买 u 盘的方法。定义购买 u 盘的接口 UsbSell
       2. 金士顿(King)对购买 1 千以上的价格是 85, 3 千以上是 80, 5 千以上是 75。 单个 120
元。定义 UsbKingFactory 类,实现 UsbSell
       3. 闪迪(San)对购买 1 千以上的价格是 82, 3 千以上是 78, 5 千以上是 72。 单个 120 元。
定义 UsbSanFactory 类,实现 UsbSell
       4. 定义淘宝的代理商 TaoBao ,实现 UsbSell
       5. 定义微商的代理商 WeiShang, 实现 UsbSell
       6. 定义测试类,测试通过淘宝, 微商购买 u 盘
    2)代码实现

(1)、定义业务接口
   定义业务接口 UsbSell(目标接口),其中含有抽象方法 sell(int amount), sell 是目标方法
public interface UsbSell {
    float sell(int amount);
}
(2)、定义接口实现类
	目标类 UsbKingFactory(金士顿 u 盘),该类实现了业务接口。
//金士顿厂商
public class UsbKingFactory implements UsbSell {

    @Override
    public float sell(int amount) {
        //参数值是要购买的数量
        //返回的是单个价格
        return 90.0f;
    }
}
(3) 代理商 TaoBao
	TaoBao 就是一个代理类, 代理厂家销售 u 盘
public class TaoBao implements UsbSell {
    private UsbKingFactory factory = new UsbKingFactory();

    @Override
    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;
        TaoBao taobao = new TaoBao();
        try {
            price = taobao.sell(1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("taobao购买价格price: " + price);
    }
}

4.3、静态代理的优缺点

优点:1)实现简单  2)容易理解。
缺点:1)代码复杂难于管理  2)代理类依赖目标类,代理类过多
5、动态代理(jdk动态代理)

5.1何为动态代理

	动态代理是指代理类对象在程序运行时由 JVM 根据反射机制动态生成的。
动态代理不需要定义代理类的.java 源文件。动态代理其实就是 jdk 运行期间,
动态创建 class 字节码并加载到 JVM。

5.2动态代理的实现方式

1)使用 JDK 代理代理
2)通过 CGLIB 动态代理。

5.3何为jdk动态代理

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

5.4 InvocationHandler 接口

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

2、InvocationHandler是一个接口,接口中只有一个invoke()方法。实现了 
InvocationHandler 接口的类用于加强目标类的主业务逻辑。这个接口中有一
个方法 invoke(),具体加强的代码逻辑就是定义在该方法中的。通过代理对象执行接口中的方法时,会自动调用 invoke()方法。

3、invoke()方法的介绍如下:
	public Object invoke ( Object proxy, Method method, Object[] args)
	proxy:代表生成的代理对象
	method:代表目标方法
	args:代表目标方法的参数
第一个参数 proxy 是 jdk 在运行时赋值的,在方法中直接使用,第二个参数后面介绍,
第三个参数是方法执行的参数, 这三个参数都是 jdk 运行时赋值的,无需程序员给出。
4、 InvocationHandler 接口怎么用:
	1.创建类实现接口InvocationHandler
	2.重写invoke()方法, 把原来静态代理中代理类要完成的功能,写在这。

5.5 Method类

1、Method类:表示方法的, 确切的说就是目标类中的方法。
   作用:通过Method可以执行某个目标类的方法,Method.invoke();
	method.invoke(目标对象,方法的参数)
	Object ret = method.invoke(service2, "李四");
	说明: method.invoke()就是用来执行目标方法的,等同于静态代理中的
	float price = factory.sell(amount); //向厂家发送订单,告诉厂家,我买了u盘,厂家发货

5.6 Proxy类

Proxy类:核心的对象,创建代理对象。之前创建对象都是 new 类的构造方法()
现在我们是使用Proxy类的方法,代替new的使用。 
	方法: 静态方法 newProxyInstance() 
	作用是: 创建代理对象, 等同于静态代理中的TaoBao taoBao = new TaoBao();
	参数:
	1. ClassLoader loader 类加载器,负责向内存中加载对象的。 使用反射获取对象的ClassLoader类a , a.getCalss().getClassLoader(),  目标对象的类加载器
	2. Class<?>[] interfaces: 接口, 目标对象实现的接口,也是反射获取的。
	3.  InvocationHandler h : 我们自己写的,代理类要完成的功能。 返回值:就是代理对象
	4、方法原形
	public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

5.7 . 实现动态代理的步骤:

1、新建一个接口,作为目标接口
2、为接口创建一个实现类,是目标类
3、创建类实现 java.lang.reflect.InvocationHandler 接口,调用目标方法并增加其他功能  
   1.调用目标方法
   2.增强功能
4.使用Proxy类的静态方法,创建代理对象。 并把返回值转为接口类型。


5.8代码实现

1、新建一个接口,作为目标接口

public interface UsbSell {
    float sell(int amount);
}

2、为接口创建一个实现类,是标类

//金士顿厂商
public class UsbKingFactory implements UsbSell {

    @Override
    public float sell(int amount) {
        //参数值是要购买的数量
        //返回的是单个价格
        return 90.0f;
    }
}

3、创建类实现 java.lang.reflect.InvocationHandler 接口,调用目标方法并增加其他功能

public class MySellHandler implements InvocationHandler {
    private Object target=null;//目标方法
    public MySellHandler(Object target) {
        //使用构造方法传入目标对象,给目标对象提供代理功能
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //执行目标方法
        Object invoke = method.invoke(proxy, args);
        float price=(float) invoke;
        //增强功能
        price=price+20;
        return price;
    }
}

4.使用Proxy类的静态方法,创建代理对象。 并把返回值转为接口类型。

public class ShopApplicationTarget {
    public static void main(String[] args) {
        //创建目标类
        UsbKingFactory target=new UsbKingFactory();
        //创建调用处理器
        InvocationHandler handler=new MySellHandler(target);
        //创建jdk动态代理
        UsbSell taobao=(UsbSell)Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                handler);
        //通过代理对象掉用业务方法实现利润增加
        float price = taobao.sell(1);
        System.out.println("taobao购买的价格:"+price);

    }
}

5运行程序的
在这里插入图片描述

6动态代理(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
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值